rgen 0.4.3 → 0.4.4

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.
Files changed (32) hide show
  1. data/CHANGELOG +6 -0
  2. data/lib/mmgen/metamodel_generator.rb +2 -1
  3. data/lib/mmgen/mm_ext/{ecore_ext.rb → ecore_mmgen_ext.rb} +3 -7
  4. data/lib/mmgen/templates/metamodel_generator.tpl +10 -8
  5. data/lib/rgen/ecore/ecore_ext.rb +69 -0
  6. data/lib/rgen/ecore/ecore_transformer.rb +1 -1
  7. data/lib/rgen/metamodel_builder/builder_extensions.rb +10 -2
  8. data/lib/rgen/serializer/xmi11_serializer.rb +101 -0
  9. data/lib/rgen/serializer/xmi20_serializer.rb +7 -7
  10. data/lib/rgen/serializer/xml_serializer.rb +47 -14
  11. data/test/ea_serializer_test.rb +29 -0
  12. data/test/ea_serializer_test/ea_testmodel_regenerated.xml +821 -0
  13. data/test/metamodel_roundtrip_test.rb +1 -2
  14. data/test/metamodel_roundtrip_test/TestModel.rb +1 -0
  15. data/test/metamodel_roundtrip_test/TestModel_Regenerated.rb +34 -35
  16. data/test/metamodel_roundtrip_test/houseMetamodel_Regenerated.ecore +128 -236
  17. data/test/rgen_test.rb +1 -0
  18. metadata +93 -95
  19. data/lib/rgen/metamodel_builder.rb.bak +0 -196
  20. data/lib/rgen/metamodel_builder/builder_extensions.rb.bak +0 -437
  21. data/lib/rgen/metamodel_builder/builder_runtime.rb.bak +0 -73
  22. data/lib/rgen/name_helper.rb.bak +0 -37
  23. data/lib/rgen/template_language.rb.bak +0 -289
  24. data/lib/rgen/template_language/directory_template_container.rb.bak +0 -69
  25. data/lib/rgen/template_language/output_handler.rb.bak +0 -88
  26. data/lib/rgen/template_language/template_container.rb.bak +0 -196
  27. data/lib/rgen/transformer.rb.bak +0 -381
  28. data/test/environment_test.rb.bak +0 -52
  29. data/test/metamodel_builder_test.rb.bak +0 -443
  30. data/test/output_handler_test.rb.bak +0 -50
  31. data/test/template_language_test.rb.bak +0 -72
  32. data/test/transformer_test.rb.bak +0 -223
@@ -1,437 +0,0 @@
1
- # RGen Framework
2
- # (c) Martin Thiede, 2006
3
-
4
- require 'erb'
5
- require 'rgen/metamodel_builder/metamodel_description.rb'
6
-
7
- module RGen
8
-
9
- module MetamodelBuilder
10
-
11
- # This module provides methods which can be used to setup a metamodel element.
12
- # The module is used to +extend+ MetamodelBuilder::MMBase, i.e. add the module's
13
- # methods as class methods.
14
- #
15
- # MetamodelBuilder::MMBase should be used as a start for new metamodel elements.
16
- # See MetamodelBuilder for an example.
17
- #
18
- module BuilderExtensions
19
- include NameHelper
20
-
21
- class FeatureBlockEvaluator
22
- def self.eval(block, props1, props2=nil)
23
- return unless block
24
- e = self.new(props1, props2)
25
- e.instance_eval(&block)
26
- end
27
- def initialize(props1, props2)
28
- @props1, @props2 = props1, props2
29
- end
30
- def annotation(hash)
31
- @props1.annotations << Intermediate::Annotation.new(hash)
32
- end
33
- def opposite_annotation(hash)
34
- raise "No opposite available" unless @props2
35
- @props2.annotations << Intermediate::Annotation.new(hash)
36
- end
37
- end
38
-
39
- def has_attr(role, target_class=nil, raw_props={}, &block)
40
- props = AttributeDescription.new(target_class, _ownProps(raw_props).merge({
41
- :name=>role, :upperBound=>1}))
42
- raise "No opposite available" unless _oppositeProps(raw_props).empty?
43
- FeatureBlockEvaluator.eval(block, props)
44
- _build_internal(props)
45
- end
46
-
47
- # Add a single attribute or unidirectional association.
48
- # 'role' specifies the name which is used to access the attribute.
49
- # 'target_class' specifies the type of objects which can be held by this attribute.
50
- # If no target class is given, String will be default.
51
- #
52
- # This class method adds the following instance methods, where 'role' is to be
53
- # replaced by the given role name:
54
- # class#role # getter
55
- # class#role=(value) # setter
56
- #
57
- def has_one(role, target_class=nil, raw_props={}, &block)
58
- props = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
59
- :name=>role, :upperBound=>1, :containment=>false}))
60
- raise "No opposite available" unless _oppositeProps(raw_props).empty?
61
- FeatureBlockEvaluator.eval(block, props)
62
- _build_internal(props)
63
- end
64
-
65
- # Add an unidirectional _many_ association.
66
- # 'role' specifies the name which is used to access the attribute.
67
- # 'target_class' is optional and can be used to fix the type of objects which
68
- # can be referenced by this association.
69
- #
70
- # This class method adds the following instance methods, where 'role' is to be
71
- # replaced by the given role name:
72
- # class#addRole(value)
73
- # class#removeRole(value)
74
- # class#role # getter, returns an array
75
- # Note that the first letter of the role name is turned into an uppercase
76
- # for the add and remove methods.
77
- #
78
- def has_many(role, target_class=nil, raw_props={}, &block)
79
- props = ReferenceDescription.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
80
- :name=>role, :containment=>false})))
81
- raise "No opposite available" unless _oppositeProps(raw_props).empty?
82
- FeatureBlockEvaluator.eval(block, props)
83
- _build_internal(props)
84
- end
85
-
86
- def contains_one_uni(role, target_class=nil, raw_props={}, &block)
87
- props = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
88
- :name=>role, :upperBound=>1, :containment=>true}))
89
- raise "No opposite available" unless _oppositeProps(raw_props).empty?
90
- FeatureBlockEvaluator.eval(block, props)
91
- _build_internal(props)
92
- end
93
-
94
- def contains_many_uni(role, target_class=nil, raw_props={}, &block)
95
- props = ReferenceDescription.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
96
- :name=>role, :containment=>true})))
97
- raise "No opposite available" unless _oppositeProps(raw_props).empty?
98
- FeatureBlockEvaluator.eval(block, props)
99
- _build_internal(props)
100
- end
101
-
102
- # Add a bidirectional one-to-many association between two classes.
103
- # The class this method is called on is refered to as _own_class_ in
104
- # the following.
105
- #
106
- # Instances of own_class can use 'own_role' to access _many_ associated instances
107
- # of type 'target_class'. Instances of 'target_class' can use 'target_role' to
108
- # access _one_ associated instance of own_class.
109
- #
110
- # This class method adds the following instance methods where 'ownRole' and
111
- # 'targetRole' are to be replaced by the given role names:
112
- # own_class#addOwnRole(value)
113
- # own_class#removeOwnRole(value)
114
- # own_class#ownRole
115
- # target_class#targetRole
116
- # target_class#targetRole=(value)
117
- # Note that the first letter of the role name is turned into an uppercase
118
- # for the add and remove methods.
119
- #
120
- # When an element is added/set on either side, this element also receives the element
121
- # is is added to as a new element.
122
- #
123
- def one_to_many(target_role, target_class, own_role, raw_props={}, &block)
124
- props1 = ReferenceDescription.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
125
- :name=>target_role, :containment=>false})))
126
- props2 = ReferenceDescription.new(self, _oppositeProps(raw_props).merge({
127
- :name=>own_role, :upperBound=>1, :containment=>false}))
128
- FeatureBlockEvaluator.eval(block, props1, props2)
129
- _build_internal(props1, props2)
130
- end
131
-
132
- def contains_many(target_role, target_class, own_role, raw_props={}, &block)
133
- props1 = ReferenceDescription.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
134
- :name=>target_role, :containment=>true})))
135
- props2 = ReferenceDescription.new(self, _oppositeProps(raw_props).merge({
136
- :name=>own_role, :upperBound=>1, :containment=>false}))
137
- FeatureBlockEvaluator.eval(block, props1, props2)
138
- _build_internal(props1, props2)
139
- end
140
-
141
- # This is the inverse of one_to_many provided for convenience.
142
- def many_to_one(target_role, target_class, own_role, raw_props={}, &block)
143
- props1 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
144
- :name=>target_role, :upperBound=>1, :containment=>false}))
145
- props2 = ReferenceDescription.new(self, _setManyUpperBound(_oppositeProps(raw_props).merge({
146
- :name=>own_role, :containment=>false})))
147
- FeatureBlockEvaluator.eval(block, props1, props2)
148
- _build_internal(props1, props2)
149
- end
150
-
151
- # Add a bidirectional many-to-many association between two classes.
152
- # The class this method is called on is refered to as _own_class_ in
153
- # the following.
154
- #
155
- # Instances of own_class can use 'own_role' to access _many_ associated instances
156
- # of type 'target_class'. Instances of 'target_class' can use 'target_role' to
157
- # access _many_ associated instances of own_class.
158
- #
159
- # This class method adds the following instance methods where 'ownRole' and
160
- # 'targetRole' are to be replaced by the given role names:
161
- # own_class#addOwnRole(value)
162
- # own_class#removeOwnRole(value)
163
- # own_class#ownRole
164
- # target_class#addTargetRole
165
- # target_class#removeTargetRole=(value)
166
- # target_class#targetRole
167
- # Note that the first letter of the role name is turned into an uppercase
168
- # for the add and remove methods.
169
- #
170
- # When an element is added on either side, this element also receives the element
171
- # is is added to as a new element.
172
- #
173
- def many_to_many(target_role, target_class, own_role, raw_props={}, &block)
174
- props1 = ReferenceDescription.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
175
- :name=>target_role, :containment=>false})))
176
- props2 = ReferenceDescription.new(self, _setManyUpperBound(_oppositeProps(raw_props).merge({
177
- :name=>own_role, :containment=>false})))
178
- FeatureBlockEvaluator.eval(block, props1, props2)
179
- _build_internal(props1, props2)
180
- end
181
-
182
- # Add a bidirectional one-to-one association between two classes.
183
- # The class this method is called on is refered to as _own_class_ in
184
- # the following.
185
- #
186
- # Instances of own_class can use 'own_role' to access _one_ associated instance
187
- # of type 'target_class'. Instances of 'target_class' can use 'target_role' to
188
- # access _one_ associated instance of own_class.
189
- #
190
- # This class method adds the following instance methods where 'ownRole' and
191
- # 'targetRole' are to be replaced by the given role names:
192
- # own_class#ownRole
193
- # own_class#ownRole=(value)
194
- # target_class#targetRole
195
- # target_class#targetRole=(value)
196
- #
197
- # When an element is set on either side, this element also receives the element
198
- # is is added to as the new element.
199
- #
200
- def one_to_one(target_role, target_class, own_role, raw_props={}, &block)
201
- props1 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
202
- :name=>target_role, :upperBound=>1, :containment=>false}))
203
- props2 = ReferenceDescription.new(self, _oppositeProps(raw_props).merge({
204
- :name=>own_role, :upperBound=>1, :containment=>false}))
205
- FeatureBlockEvaluator.eval(block, props1, props2)
206
- _build_internal(props1, props2)
207
- end
208
-
209
- def contains_one(target_role, target_class, own_role, raw_props={}, &block)
210
- props1 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
211
- :name=>target_role, :upperBound=>1, :containment=>true}))
212
- props2 = ReferenceDescription.new(self, _oppositeProps(raw_props).merge({
213
- :name=>own_role, :upperBound=>1, :containment=>false}))
214
- FeatureBlockEvaluator.eval(block, props1, props2)
215
- _build_internal(props1, props2)
216
- end
217
-
218
- def _metamodel_description # :nodoc:
219
- @metamodel_description ||= []
220
- end
221
-
222
- def inherited(c)
223
- c._class_module
224
- end
225
-
226
- def _class_module # :nodoc:
227
- unless const_defined?(:ClassModule)
228
- const_set(:ClassModule, Module.new)
229
- include const_get(:ClassModule)
230
- end
231
- const_get(:ClassModule)
232
- end
233
-
234
- protected
235
-
236
- # Central builder method
237
- #
238
- def _build_internal(props1, props2=nil)
239
- _metamodel_description << props1
240
- if props1.is_a?(ReferenceDescription) && props1.many?
241
- _build_many_methods(props1, props2)
242
- else
243
- _build_one_methods(props1, props2)
244
- end
245
- if props2
246
- # this is a bidirectional reference
247
- props1.opposite, props2.opposite = props2, props1
248
- other_class = props1.impl_type
249
- other_class._metamodel_description << props2
250
- raise "Internal error: second description must be a ReferenceDescription" \
251
- unless props2.is_a?(ReferenceDescription)
252
- if props2.many?
253
- other_class._build_many_methods(props2, props1)
254
- else
255
- other_class._build_one_methods(props2, props1)
256
- end
257
- end
258
- end
259
-
260
- # To-One association methods
261
- #
262
- def _build_one_methods(props, other_props=nil)
263
- name = props.value(:name)
264
- other_role = other_props && other_props.value(:name)
265
- other_kind = other_props && ( other_props.many? ? :many : :one )
266
-
267
- if props.value(:derived)
268
- build_derived_method(name, props, :one)
269
- else
270
- @@one_read_builder ||= ERB.new <<-CODE
271
-
272
- def <%= name %>
273
- <% if props.is_a?(AttributeDescription) && props.value(:defaultValueLiteral) %>
274
- <% defVal = props.value(:defaultValueLiteral) %>
275
- <% defVal = '"'+defVal+'"' if props.impl_type == String %>
276
- <% defVal = ':'+defVal if props.impl_type.is_a?(DataTypes::Enum) && props.impl_type != DataTypes::Boolean %>
277
- @<%= name %>.nil? ? <%= defVal %> : @<%= name %>
278
- <% else %>
279
- @<%= name %>
280
- <% end %>
281
- end
282
- alias get<%= firstToUpper(name) %> <%= name %>
283
-
284
- CODE
285
- _class_module.module_eval(@@one_read_builder.result(binding))
286
- end
287
-
288
- if props.value(:changeable)
289
- @@one_write_builder ||= ERB.new <<-CODE
290
-
291
- def <%= name %>=(val)
292
- return if val == @<%= name %>
293
- <%= type_check_code("val", props) %>
294
- oldval = @<%= name %>
295
- @<%= name %> = val
296
- <% if other_role && other_kind %>
297
- _unregister(self,oldval,"<%= other_role %>","<%= other_kind %>")
298
- _register(self,val,"<%= other_role %>","<%= other_kind %>")
299
- <% end %>
300
- end
301
- alias set<%= firstToUpper(name) %> <%= name %>=
302
-
303
- CODE
304
- _class_module.module_eval(@@one_write_builder.result(binding))
305
-
306
- end
307
- end
308
-
309
- # To-Many association methods
310
- #
311
- def _build_many_methods(props, other_props=nil)
312
- name = props.value(:name)
313
- other_role = other_props && other_props.value(:name)
314
- other_kind = other_props && ( other_props.many? ? :many : :one )
315
-
316
- if props.value(:derived)
317
- build_derived_method(name, props, :many)
318
- else
319
- @@many_read_builder ||= ERB.new <<-CODE
320
-
321
- def <%= name %>
322
- ( @<%= name %> ? @<%= name %>.dup : [] )
323
- end
324
- alias get<%= firstToUpper(name) %> <%= name %>
325
-
326
- CODE
327
- _class_module.module_eval(@@many_read_builder.result(binding))
328
- end
329
-
330
- if props.value(:changeable)
331
- @@many_write_builder ||= ERB.new <<-CODE
332
-
333
- def add<%= firstToUpper(name) %>(val)
334
- @<%= name %> = [] unless @<%= name %>
335
- return if val.nil? or @<%= name %>.include?(val)
336
- <%= type_check_code("val", props) %>
337
- @<%= name %>.push val
338
- <% if other_role && other_kind %>
339
- _register(self, val, "<%= other_role %>", "<%= other_kind %>")
340
- <% end %>
341
- end
342
-
343
- def remove<%= firstToUpper(name) %>(val)
344
- @<%= name %> = [] unless @<%= name %>
345
- return unless @<%= name %>.include?(val)
346
- @<%= name %>.delete val
347
- <% if other_role && other_kind %>
348
- _unregister(self, val, "<%= other_role %>", "<%= other_kind %>")
349
- <% end %>
350
- end
351
-
352
- def <%= name %>=(val)
353
- return if val.nil?
354
- raise _assignmentTypeError(self, val, Array) unless val.is_a? Array
355
- getGeneric(:<%= name %>).each {|e|
356
- remove<%= firstToUpper(name) %>(e)
357
- }
358
- val.each {|v|
359
- add<%= firstToUpper(name) %>(v)
360
- }
361
- end
362
- alias set<%= firstToUpper(name) %> <%= name %>=
363
-
364
- CODE
365
- _class_module.module_eval(@@many_write_builder.result(binding))
366
- end
367
-
368
- end
369
-
370
- private
371
-
372
- def build_derived_method(name, props, kind)
373
- raise "Implement method #{name}_derived instead of method #{name}" \
374
- if (public_instance_methods+protected_instance_methods+private_instance_methods).include?(name)
375
- @@derived_builder ||= ERB.new <<-CODE
376
-
377
- def <%= name %>
378
- raise "Derived feature requires public implementation of method <%= name %>_derived" \
379
- unless respond_to?(:<%= name+"_derived" %>)
380
- val = <%= name %>_derived
381
- <% if kind == :many %>
382
- raise _assignmentTypeError(self,val,Array) unless val && val.is_a?(Array)
383
- val.each do |v|
384
- <%= type_check_code("v", props) %>
385
- end
386
- <% else %>
387
- <%= type_check_code("val", props) %>
388
- <% end %>
389
- val
390
- end
391
- alias get<%= firstToUpper(name) %> <%= name %>
392
- #TODO final_method :<%= name %>
393
-
394
- CODE
395
- _class_module.module_eval(@@derived_builder.result(binding))
396
- end
397
-
398
- def type_check_code(varname, props)
399
- code = ""
400
- if props.impl_type.is_a?(Class)
401
- code << "unless #{varname}.nil? or #{varname}.is_a? #{props.impl_type}\n"
402
- expected = props.impl_type.to_s
403
- elsif props.impl_type.is_a?(RGen::MetamodelBuilder::DataTypes::Enum)
404
- code << "unless #{varname}.nil? or [#{props.impl_type.literals_as_strings.join(',')}].include?(#{varname})\n"
405
- expected = "["+props.impl_type.literals_as_strings.join(',')+"]"
406
- else
407
- raise StandardError.new("Unkown type "+props.impl_type.to_s)
408
- end
409
- code << "raise _assignmentTypeError(self,#{varname},\"#{expected}\")\n"
410
- code << "end"
411
- code
412
- end
413
-
414
- def _ownProps(props)
415
- Hash[*(props.select{|k,v| !(k.to_s =~ /^opposite_/)}.flatten)]
416
- end
417
-
418
- def _oppositeProps(props)
419
- r = {}
420
- props.each_pair do |k,v|
421
- if k.to_s =~ /^opposite_(.*)$/
422
- r[$1.to_sym] = v
423
- end
424
- end
425
- r
426
- end
427
-
428
- def _setManyUpperBound(props)
429
- props[:upperBound] = -1 unless props[:upperBound].is_a?(Integer) && props[:upperBound] > 1
430
- props
431
- end
432
-
433
- end
434
-
435
- end
436
-
437
- end
@@ -1,73 +0,0 @@
1
- # RGen Framework
2
- # (c) Martin Thiede, 2006
3
-
4
- require 'rgen/name_helper'
5
-
6
- module RGen
7
-
8
- module MetamodelBuilder
9
-
10
- # This module is mixed into MetamodelBuilder::MMBase.
11
- # The methods provided by this module are used by the methods generated
12
- # by the class methods of MetamodelBuilder::BuilderExtensions
13
- module BuilderRuntime
14
- include NameHelper
15
-
16
- def is_a?(c)
17
- return super unless c.respond_to?(:_class_module)
18
- kind_of?(c._class_module)
19
- end
20
-
21
- def addGeneric(role, value)
22
- send("add#{firstToUpper(role)}",value)
23
- end
24
-
25
- def removeGeneric(role, value)
26
- send("remove#{firstToUpper(role)}",value)
27
- end
28
-
29
- def setGeneric(role, value)
30
- send("#{role}=",value)
31
- end
32
-
33
- def getGeneric(role)
34
- send("#{role}")
35
- end
36
-
37
- def _unregister(element, target, target_role, kind)
38
- return unless element and target and target_role
39
- if kind == 'one'
40
- target.send("#{target_role}=",nil)
41
- elsif kind == 'many'
42
- target.send("remove#{firstToUpper(target_role)}",element)
43
- end
44
- end
45
-
46
- def _register(element, target, target_role, kind)
47
- return unless element and target and target_role
48
- if kind == 'one'
49
- target.send("#{target_role}=",element)
50
- elsif kind == 'many'
51
- target.send("add#{firstToUpper(target_role)}",element)
52
- end
53
- end
54
-
55
- def _assignmentTypeError(target, value, expected)
56
- text = ""
57
- if target
58
- targetId = target.class.name
59
- targetId += "(" + target.name + ")" if target.respond_to?(:name) and target.name
60
- text += "In #{targetId} : "
61
- end
62
- valueId = value.class.name
63
- valueId += "(" + value.name + ")" if value.respond_to?(:name) and value.name
64
- valueId += "(:" + value.to_s + ")" if value.is_a?(Symbol)
65
- text += "Can not use a #{valueId} where a #{expected} is expected"
66
- StandardError.new(text)
67
- end
68
-
69
- end
70
-
71
- end
72
-
73
- end