modelmaker 0.1.2

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.
data/src/bin/modelmake ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'modelmaker'
4
+
5
+ ModelMaker::DefaultRunner.new().run()
@@ -0,0 +1,386 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'erb'
4
+
5
+ module ModelMaker
6
+ class Project
7
+ attr_accessor :name, :copyright, :class_prefix, :entities
8
+
9
+ def initialize
10
+ @entities = []
11
+ end
12
+
13
+ def add_entity(entity)
14
+ entity.project = self
15
+ @entities << entity
16
+ end
17
+ end
18
+
19
+ class ProjectBuilder
20
+ def initialize(project)
21
+ @project = project
22
+ end
23
+
24
+ def project(name)
25
+ @project.name = name
26
+ end
27
+
28
+ def class_prefix(prefix)
29
+ @project.class_prefix = prefix
30
+ end
31
+
32
+ def copyright(copyright)
33
+ @project.copyright = copyright
34
+ end
35
+
36
+ def object(name, &configuration)
37
+ builder = EntityBuilder.new(name, &configuration)
38
+ @project.add_entity(builder.entity)
39
+ end
40
+ end
41
+
42
+ class EntityBuilder
43
+ attr_reader :entity
44
+
45
+ def initialize(entity_name, &configuration)
46
+ @entity = Entity.new(entity_name)
47
+ instance_eval(&configuration)
48
+ end
49
+
50
+ def inherits(superclass)
51
+ @entity.superclass = superclass
52
+ end
53
+
54
+ def conforms_to(protocol)
55
+ @entity.protocols << protocol
56
+ end
57
+
58
+ # There was a way to do that better... "define_all" or something
59
+ def string(propname)
60
+ add_property(StringProperty.new(propname))
61
+ end
62
+
63
+ def int(propname)
64
+ add_property(IntegerProperty.new(propname))
65
+ end
66
+
67
+ def set(propname)
68
+ add_property(SetProperty.new(propname))
69
+ end
70
+
71
+ def url(propname)
72
+ add_property(UrlProperty.new(propname))
73
+ end
74
+
75
+ def array(propname)
76
+ add_property(ArrayProperty.new(propname))
77
+ end
78
+
79
+ def date(propname)
80
+ add_property(DateProperty.new(propname))
81
+ end
82
+
83
+ def add_property(property)
84
+ @entity.add_property(property)
85
+ end
86
+ end
87
+
88
+ class Entity
89
+ attr_reader :name
90
+ attr_accessor :superclass, :protocols, :project
91
+
92
+ def initialize(name)
93
+ @name = name
94
+
95
+ @superclass = 'NSObject'
96
+ @properties = {}
97
+ @protocols = []
98
+ end
99
+
100
+ def short_name
101
+ @name
102
+ end
103
+
104
+ def class_name
105
+ if @project
106
+ "#{@project.class_prefix}#{@name}"
107
+ else
108
+ @name
109
+ end
110
+ end
111
+
112
+ alias :name :class_name
113
+
114
+ def instance_name
115
+ name = @name.clone
116
+ name[0] = name[0].downcase
117
+ name
118
+ end
119
+
120
+ def add_property(property)
121
+ @properties[property.name] = property
122
+ end
123
+
124
+ def properties
125
+ @properties.values
126
+ end
127
+
128
+ def needs_init?
129
+ for property in properties do
130
+ if property.needs_init?
131
+ return true
132
+ end
133
+ end
134
+
135
+ return false
136
+ end
137
+ end
138
+
139
+ class Property
140
+ attr_reader :name
141
+
142
+ def initialize(name)
143
+ @name = name
144
+ end
145
+
146
+ def internal_type
147
+ type
148
+ end
149
+
150
+ def exposed_type
151
+ type
152
+ end
153
+
154
+ def internal_name
155
+ "_#{@name}"
156
+ end
157
+
158
+ def exposed_name
159
+ @name
160
+ end
161
+
162
+ def type
163
+ raise "Implement me, or override internal_type and external_type"
164
+ end
165
+
166
+ def needs_init?
167
+ false
168
+ end
169
+
170
+ def init_line
171
+ nil
172
+ end
173
+
174
+ def setter_signature
175
+ name = exposed_name.to_s
176
+ name[0] = name[0].upcase
177
+ "- (void)set#{name}:(#{exposed_type})#{exposed_name}"
178
+ end
179
+
180
+ def assignation_value
181
+ exposed_name
182
+ end
183
+ end
184
+
185
+ class StringProperty < Property
186
+ def type
187
+ 'NSString *'
188
+ end
189
+ end
190
+
191
+ class IntegerProperty < Property
192
+ def type
193
+ 'NSInteger'
194
+ end
195
+ end
196
+
197
+ class UrlProperty < Property
198
+ def type
199
+ 'NSURL *'
200
+ end
201
+ end
202
+
203
+ class DateProperty < Property
204
+ def type
205
+ 'NSDate *'
206
+ end
207
+ end
208
+
209
+ class SetProperty < Property
210
+ def internal_type
211
+ 'NSMutableSet *'
212
+ end
213
+
214
+ def exposed_type
215
+ 'NSSet *'
216
+ end
217
+
218
+ def needs_init?
219
+ true
220
+ end
221
+
222
+ def init_line
223
+ "#{internal_name} = [[NSMutableSet alloc] init]"
224
+ end
225
+
226
+ def assignation_value
227
+ "[[NSMutableSet alloc] initWithSet:#{exposed_name}]"
228
+ end
229
+ end
230
+
231
+ class ArrayProperty < Property
232
+ def internal_type
233
+ 'NSMutableArray *'
234
+ end
235
+
236
+ def exposed_type
237
+ 'NSArray *'
238
+ end
239
+
240
+ def needs_init?
241
+ true
242
+ end
243
+
244
+ def init_line
245
+ "#{internal_name} = [[NSMutableArray alloc] init]";
246
+ end
247
+
248
+ def assignation_value
249
+ "[[NSMutableArray alloc] initWithArray:#{exposed_name}]"
250
+ end
251
+ end
252
+
253
+ class DefaultRunner
254
+ attr_accessor :pathname
255
+
256
+ def initialize
257
+ @pathname = 'Model' # Look for a file 'Model' in this directory
258
+ end
259
+
260
+ def run
261
+ if not File.exists?(@pathname)
262
+ raise 'No "Model" file found in the current directory'
263
+ end
264
+
265
+ project = Project.new()
266
+ source = File.new(@pathname).read()
267
+
268
+ builder = ProjectBuilder.new(project)
269
+ builder.instance_eval(source, @pathname, 1)
270
+
271
+ generator = Source::Generator.new(project)
272
+ generator.generate()
273
+ end
274
+ end
275
+
276
+ module Source
277
+ class Generator
278
+ def initialize(project)
279
+ @project = project
280
+ end
281
+
282
+ def generate(target_directory='.')
283
+ for cls in renderers do
284
+ renderer = cls.new()
285
+
286
+ for entity in @project.entities
287
+ vars = TemplateVars.new()
288
+ vars.project = @project
289
+ vars.entity = entity
290
+
291
+ filename = renderer.generated_file(vars)
292
+ fullpath = File.join(target_directory, filename)
293
+ fhandle = File.new(fullpath, 'w')
294
+ fhandle.write(renderer.result(vars))
295
+ end
296
+ end
297
+ end
298
+
299
+ def renderers
300
+ [
301
+ HeaderRenderer,
302
+ ImplementationRenderer,
303
+ BuilderHeaderRenderer,
304
+ BuilderImplementationRenderer
305
+ ]
306
+ end
307
+ end
308
+
309
+ class TemplateVars
310
+ attr_accessor :entity, :project, :file
311
+
312
+ def get_binding
313
+ binding
314
+ end
315
+ end
316
+
317
+ class BaseRenderer
318
+ def template_file
319
+ raise 'Implement me'
320
+ end
321
+
322
+ def generated_file(template_vars)
323
+ raise 'Implement me'
324
+ end
325
+
326
+ def result(template_vars)
327
+ renderer.result(template_vars.get_binding)
328
+ end
329
+
330
+ def renderer
331
+ if not @renderer
332
+ mydir = File.dirname(__FILE__)
333
+ template_path = File.join(mydir, '../templates', template_file)
334
+ template = File.new(template_path).read()
335
+ @renderer = ERB.new(template, 0, '>')
336
+ end
337
+
338
+ @renderer
339
+ end
340
+ end
341
+
342
+ class HeaderRenderer < BaseRenderer
343
+ def template_file
344
+ 'header.erb'
345
+ end
346
+
347
+ def generated_file(template_vars)
348
+ "#{template_vars.entity.name}.h"
349
+ end
350
+ end
351
+
352
+ class ImplementationRenderer < BaseRenderer
353
+ def template_file
354
+ 'implementation.erb'
355
+ end
356
+
357
+ def generated_file(template_vars)
358
+ "#{template_vars.entity.name}.m"
359
+ end
360
+ end
361
+
362
+ class BuilderHeaderRenderer < BaseRenderer
363
+ def template_file
364
+ 'builder_header.erb'
365
+ end
366
+
367
+ def generated_file(template_vars)
368
+ "#{template_vars.entity.name}Builder.h"
369
+ end
370
+ end
371
+
372
+ class BuilderImplementationRenderer < BaseRenderer
373
+ def template_file
374
+ 'builder_implementation.erb'
375
+ end
376
+
377
+ def generated_file(template_vars)
378
+ "#{template_vars.entity.name}Builder.m"
379
+ end
380
+ end
381
+
382
+ class FileInfo
383
+ attr_accessor :pathname
384
+ end
385
+ end
386
+ end
@@ -0,0 +1,27 @@
1
+ //
2
+ // <%= entity.name %>Builder.h
3
+ // <%= project.name %>
4
+
5
+ <% if project.copyright %>
6
+ //
7
+ // Copyright (c) <%= project.copyright %>. All rights reserved.
8
+ <% end %>
9
+ //
10
+ // Generated by ModelMaker
11
+ // See http://github.com/aspyct/ModelMaker
12
+ //
13
+
14
+ #import <Foundation/Foundation.h>
15
+ #import "<%= entity.name %>.h"
16
+
17
+ @interface <%= entity.name %>Builder : NSObject
18
+
19
+ @property (readonly) <%= entity.name %> *<%= entity.instance_name %>;
20
+
21
+ - (id)init;
22
+
23
+ <% for property in entity.properties %>
24
+ <%= property.setter_signature %>;
25
+ <% end %>
26
+
27
+ @end
@@ -0,0 +1,36 @@
1
+ //
2
+ // <%= entity.name %>Builder.m
3
+ // <%= project.name %>
4
+
5
+ <% if project.copyright %>
6
+ //
7
+ // Copyright (c) <%= project.copyright %>. All rights reserved.
8
+ <% end %>
9
+ //
10
+ // Generated by ModelMaker
11
+ // See http://github.com/aspyct/ModelMaker
12
+ //
13
+
14
+ #import "<%= entity.name %>Builder.h"
15
+
16
+ @implementation <%= entity.name %>Builder
17
+
18
+ @synthesize <%= entity.instance_name %> = _<%= entity.instance_name %>;
19
+
20
+ - (id)init {
21
+ self = [super init];
22
+
23
+ if (self) {
24
+ _<%= entity.instance_name %> = [[<%= entity.name %> alloc] init];
25
+ }
26
+
27
+ return self;
28
+ }
29
+
30
+ <% for property in entity.properties %>
31
+ <%= property.setter_signature %> {
32
+ _<%= entity.instance_name %>-><%= property.internal_name %> = <%= property.assignation_value %>;
33
+ }
34
+
35
+ <% end %>
36
+ @end
@@ -0,0 +1,27 @@
1
+ //
2
+ // <%= entity.name %>.h
3
+ // <%= project.name %>
4
+
5
+ <% if project.copyright %>
6
+ //
7
+ // Copyright (c) <%= project.copyright %>. All rights reserved.
8
+ <% end %>
9
+ //
10
+ // Generated by ModelMaker
11
+ // See http://github.com/aspyct/ModelMaker
12
+ //
13
+
14
+ #import <Foundation/Foundation.h>
15
+
16
+ @interface <%= @entity.name %> : <%= @entity.superclass %> <%= '<' + @entity.protocols.join(', ') + '> ' if not @entity.protocols.empty? %>{
17
+ @package
18
+ <% for @property in @entity.properties %>
19
+ <%= @property.internal_type %> <%= @property.internal_name %>;
20
+ <% end %>
21
+ }
22
+
23
+ <% for @property in @entity.properties %>
24
+ @property (readonly) <%= @property.exposed_type %> <%= @property.exposed_name %>;
25
+ <% end %>
26
+
27
+ @end
@@ -0,0 +1,38 @@
1
+ //
2
+ // <%= entity.name %>.m
3
+ // <%= project.name %>
4
+
5
+ <% if project.copyright %>
6
+ //
7
+ // Copyright (c) <%= project.copyright %>. All rights reserved.
8
+ <% end %>
9
+ //
10
+ // Generated by ModelMaker
11
+ // See http://github.com/aspyct/ModelMaker
12
+ //
13
+
14
+ #import "<%= @entity.name %>.h"
15
+
16
+ @implementation <%= @entity.name %>
17
+
18
+
19
+ <% for @property in @entity.properties %>
20
+ @synthesize <%= @property.exposed_name %> = <%= @property.internal_name %>;
21
+ <% end %>
22
+
23
+ <% if @entity.needs_init? %>
24
+ - (id)init
25
+ {
26
+ self = [super init];
27
+
28
+ if (self) {
29
+ <% for @property in @entity.properties %><% if @property.needs_init? %>
30
+ <%= @property.init_line %>;
31
+ <% end %><% end %>
32
+ }
33
+
34
+ return self;
35
+ }
36
+
37
+ <% end %>
38
+ @end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: modelmaker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Antoine d'Otreppe
9
+ autorequire:
10
+ bindir: src/bin
11
+ cert_chain: []
12
+ date: 2012-10-16 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! 'ModelMaker generates your model classes based on a simple ruby definition. '
15
+ email: a.dotreppe@aspyct.org
16
+ executables:
17
+ - modelmake
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - src/templates/builder_header.erb
22
+ - src/templates/builder_implementation.erb
23
+ - src/templates/header.erb
24
+ - src/templates/implementation.erb
25
+ - src/bin/modelmake
26
+ - src/lib/modelmaker.rb
27
+ homepage: https://github.com/aspyct/ModelMaker
28
+ licenses:
29
+ - MIT
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - src/lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 1.8.24
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: Objective-C model class generator
52
+ test_files: []
53
+ has_rdoc: