rgen 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
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