rgen 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -151,3 +151,13 @@
151
151
  * Fixed metamodel generator to quote illegal enum literal symbols
152
152
  * Imporved UML to ECore transformer and EA support
153
153
 
154
+ =0.6.1
155
+
156
+ * Fixed metamodel builder to not overwrite a model element's 'class' method
157
+ * Added enum type transformation to ECoreToUML13 transformer, primitive type mapping based on instanceClassName
158
+ * Fixed default value appearing on read after setting a feature value to nil
159
+ * Added eIsSet and eUnset methods
160
+ * Added eContainer and eContainingFeature methods
161
+ * Fixed ModelFragment#elements not containing root elements
162
+ * Added optional output of invalidation reason to FileCacheMap#load_data
163
+
data/README.rdoc ADDED
@@ -0,0 +1,78 @@
1
+ = RGen - Ruby Modelling and Generator Framework
2
+
3
+ RGen is a framework for Model Driven Software Development (MDSD)in Ruby.
4
+ This means that it helps you build Metamodels, instantiate Models, modify
5
+ and transform Models and finally generate arbitrary textual content from it.
6
+
7
+ RGen features include:
8
+ * Supporting Ruby 1.8.6, 1.8.7 and 1.9.x
9
+ * Metamodel definition language (internal Ruby DSL)
10
+ * ECore Meta-metamodel with an ECore instance available for every Metamodel
11
+ * Generator creating the Ruby metamodel definition from an ECore instance
12
+ * Transformer creating Ruby metamodel classes/modules from an ECore instance
13
+ * Instantiation of Metamodels, i.e. creation of Models (e.g. from XML)
14
+ * Model builder, internal Ruby DSL
15
+ * Model fragmentation over several several files and per-fragment caching
16
+ * Model Transformation language (internal Ruby DSL)
17
+ * Powerful template based generator language (internal Ruby DSL inside of ERB)
18
+ * UML 1.3 metamodel and XMI 1.1 instantiator included
19
+ * ECore XML support (XMI 2.0)
20
+ * UML-to-ECore and ECore-to-UML transformation (UML class models)
21
+ * Enterprise Architect support (UML1.3/XMI1.1)
22
+
23
+
24
+ == Download
25
+
26
+ Get the latest release from Github: https://github.com/mthiede/rgen
27
+
28
+
29
+ == Installation
30
+
31
+ Install RGen as a Ruby gem:
32
+
33
+ gem install rgen
34
+
35
+
36
+ == Running the Tests
37
+
38
+ Change to the 'test' folder and run the test suite:
39
+
40
+ cd test
41
+ ruby rgen_test.rb
42
+
43
+
44
+ == Documentation
45
+
46
+ RDoc documentation is available at Github: http://mthiede.github.com/rgen/
47
+
48
+ Find the main documentation parts for:
49
+ * RGen::MetamodelBuilder
50
+ * RGen::Transformer
51
+ * RGen::TemplateLanguage
52
+ * RGen::Fragment::FragmentedModel
53
+
54
+
55
+ == Examples
56
+
57
+ There are several examples of using RGen within the framework itself.
58
+
59
+ Metamodel Definition:
60
+ lib/rgen/ecore/ecore.rb
61
+ lib/metamodels/uml13_metamodel.rb
62
+
63
+ Instantiation:
64
+ lib/rgen/instantiator/xmi11_instantiator.rb
65
+ lib/rgen/instantiator/ecore_xml_instantiator.rb
66
+
67
+ Transformations:
68
+ lib/rgen/ecore/ruby_to_ecore.rb
69
+ lib/transformers/uml13_to_ecore.rb
70
+
71
+ Generators:
72
+ lib/mmgen/metamodel_generator.rb
73
+
74
+
75
+ == License
76
+
77
+ RGen is released under the MIT license.
78
+
data/Rakefile CHANGED
@@ -1,41 +1,37 @@
1
- require 'rake/gempackagetask'
2
- require 'rake/rdoctask'
1
+ require 'rubygems/package_task'
2
+ require 'rdoc/task'
3
3
 
4
4
  RGenGemSpec = Gem::Specification.new do |s|
5
5
  s.name = %q{rgen}
6
- s.version = "0.6.0"
6
+ s.version = "0.6.1"
7
7
  s.date = Time.now.strftime("%Y-%m-%d")
8
8
  s.summary = %q{Ruby Modelling and Generator Framework}
9
9
  s.email = %q{martin dot thiede at gmx de}
10
10
  s.homepage = %q{http://ruby-gen.org}
11
11
  s.rubyforge_project = %q{rgen}
12
- s.description = %q{RGen is a framework supporting Model Driven Software Development (MDSD). This means that it helps you build Metamodels, instantiate Models, modify and transform Models and finally generate arbitrary textual content from it.}
12
+ s.description = %q{RGen is a framework for Model Driven Software Development (MDSD) in Ruby. This means that it helps you build Metamodels, instantiate Models, modify and transform Models and finally generate arbitrary textual content from it.}
13
13
  s.authors = ["Martin Thiede"]
14
14
  gemfiles = Rake::FileList.new
15
15
  gemfiles.include("{lib,test}/**/*")
16
- gemfiles.include("README", "CHANGELOG", "MIT-LICENSE", "Rakefile")
16
+ gemfiles.include("README.rdoc", "CHANGELOG", "MIT-LICENSE", "Rakefile")
17
17
  gemfiles.exclude(/\b\.bak\b/)
18
18
  s.files = gemfiles
19
- s.rdoc_options = ["--main", "README", "-x", "test", "-x", "metamodels", "-x", "ea_support/uml13*"]
20
- s.extra_rdoc_files = ["README", "CHANGELOG", "MIT-LICENSE"]
19
+ s.rdoc_options = ["--main", "README.rdoc", "-x", "test", "-x", "metamodels", "-x", "ea_support/uml13*"]
20
+ s.extra_rdoc_files = ["README.rdoc", "CHANGELOG", "MIT-LICENSE"]
21
21
  end
22
22
 
23
- Rake::RDocTask.new do |rd|
24
- rd.main = "README"
25
- rd.rdoc_files.include("README", "CHANGELOG", "MIT-LICENSE", "lib/**/*.rb")
26
- rd.rdoc_files.exclude("lib/metamodels")
23
+ RDoc::Task.new do |rd|
24
+ rd.main = "README.rdoc"
25
+ rd.rdoc_files.include("README.rdoc", "CHANGELOG", "MIT-LICENSE", "lib/**/*.rb")
26
+ rd.rdoc_files.exclude("lib/metamodels/*")
27
27
  rd.rdoc_files.exclude("lib/ea_support/uml13*")
28
28
  rd.rdoc_dir = "doc"
29
29
  end
30
30
 
31
- RGenPackageTask = Rake::GemPackageTask.new(RGenGemSpec) do |p|
32
- p.need_zip = true
31
+ RGenPackageTask = Gem::PackageTask.new(RGenGemSpec) do |p|
32
+ p.need_zip = false
33
33
  end
34
34
 
35
- task :publish_doc do
36
- sh %{pscp -r doc/* thiedem@rubyforge.org:/var/www/gforge-projects/rgen}
37
- end
38
-
39
35
  task :prepare_package_rdoc => :rdoc do
40
36
  RGenPackageTask.package_files.include("doc/**/*")
41
37
  end
@@ -99,6 +99,7 @@ class ModelFragment
99
99
  return @elements if @elements
100
100
  @elements = []
101
101
  @root_elements.each do |e|
102
+ @elements << e
102
103
  all_child_elements(e, @elements)
103
104
  end
104
105
  @elements
@@ -201,6 +201,9 @@ module MetamodelBuilder
201
201
 
202
202
  # Instances of MMGeneric can be used as values of any attribute are reference
203
203
  class MMGeneric
204
+ # empty implementation so we don't have to check if a value is a MMGeneriv before setting the container
205
+ def _set_container(container, containing_feature_name)
206
+ end
204
207
  end
205
208
 
206
209
  # MMProxy objects can be used instead of real target elements in case references should be resolved later on
@@ -306,18 +306,20 @@ module BuilderExtensions
306
306
  else
307
307
  @@one_read_builder ||= ERB.new <<-CODE
308
308
 
309
- def <%= name %>
309
+ def get<%= firstToUpper(name) %>
310
310
  <% if !props.reference? && props.value(:defaultValueLiteral) %>
311
311
  <% defVal = props.value(:defaultValueLiteral) %>
312
312
  <% check_default_value_literal(defVal, props) %>
313
313
  <% defVal = '"'+defVal+'"' if props.impl_type == String %>
314
314
  <% defVal = ':'+defVal if props.impl_type.is_a?(DataTypes::Enum) && props.impl_type != DataTypes::Boolean %>
315
- @<%= name %>.nil? ? <%= defVal %> : @<%= name %>
315
+ (defined? @<%= name %>) ? @<%= name %> : <%= defVal %>
316
316
  <% else %>
317
317
  @<%= name %>
318
318
  <% end %>
319
319
  end
320
- alias get<%= firstToUpper(name) %> <%= name %>
320
+ <% if name != "class" %>
321
+ alias <%= name %> get<%= firstToUpper(name) %>
322
+ <% end %>
321
323
 
322
324
  CODE
323
325
  self::ClassModule.module_eval(@@one_read_builder.result(binding))
@@ -326,8 +328,8 @@ module BuilderExtensions
326
328
  if props.value(:changeable)
327
329
  @@one_write_builder ||= ERB.new <<-CODE
328
330
 
329
- def <%= name %>=(val)
330
- return if val == @<%= name %>
331
+ def set<%= firstToUpper(name) %>(val)
332
+ return if (defined? @<%= name %>) && val == @<%= name %>
331
333
  <%= type_check_code("val", props) %>
332
334
  oldval = @<%= name %>
333
335
  @<%= name %> = val
@@ -335,17 +337,28 @@ module BuilderExtensions
335
337
  oldval._unregister<%= firstToUpper(other_role) %>(self) unless oldval.nil? || oldval.is_a?(MMGeneric)
336
338
  val._register<%= firstToUpper(other_role) %>(self) unless val.nil? || val.is_a?(MMGeneric)
337
339
  <% end %>
340
+ <% if props.reference? && props.value(:containment) %>
341
+ val._set_container(self, :<%= name %>) unless val.nil?
342
+ oldval._set_container(nil, nil) unless oldval.nil?
343
+ <% end %>
338
344
  end
339
- alias set<%= firstToUpper(name) %> <%= name %>=
345
+ alias <%= name %>= set<%= firstToUpper(name) %>
340
346
 
341
347
  def _register<%= firstToUpper(name) %>(val)
342
348
  <% if other_role %>
343
349
  @<%= name %>._unregister<%= firstToUpper(other_role) %>(self) unless @<%= name %>.nil? || @<%= name %>.is_a?(MMGeneric)
344
350
  <% end %>
351
+ <% if props.reference? && props.value(:containment) %>
352
+ @<%= name %>._set_container(nil, nil) unless @<%= name %>.nil?
353
+ val._set_container(self, :<%= name %>) unless val.nil?
354
+ <% end %>
345
355
  @<%= name %> = val
346
356
  end
347
357
 
348
358
  def _unregister<%= firstToUpper(name) %>(val)
359
+ <% if props.reference? && props.value(:containment) %>
360
+ @<%= name %>._set_container(nil, nil) unless @<%= name %>.nil?
361
+ <% end %>
349
362
  @<%= name %> = nil
350
363
  end
351
364
 
@@ -366,10 +379,12 @@ module BuilderExtensions
366
379
  else
367
380
  @@many_read_builder ||= ERB.new <<-CODE
368
381
 
369
- def <%= name %>
382
+ def get<%= firstToUpper(name) %>
370
383
  ( @<%= name %> ? @<%= name %>.dup : [] )
371
384
  end
372
- alias get<%= firstToUpper(name) %> <%= name %>
385
+ <% if name != "class" %>
386
+ alias <%= name %> get<%= firstToUpper(name) %>
387
+ <% end %>
373
388
 
374
389
  CODE
375
390
  self::ClassModule.module_eval(@@many_read_builder.result(binding))
@@ -386,6 +401,9 @@ module BuilderExtensions
386
401
  <% if other_role %>
387
402
  val._register<%= firstToUpper(other_role) %>(self) unless val.is_a?(MMGeneric)
388
403
  <% end %>
404
+ <% if props.reference? && props.value(:containment) %>
405
+ val._set_container(self, :<%= name %>)
406
+ <% end %>
389
407
  end
390
408
 
391
409
  def remove<%= firstToUpper(name) %>(val)
@@ -393,6 +411,9 @@ module BuilderExtensions
393
411
  @<%= name %>.each_with_index do |e,i|
394
412
  if e.object_id == val.object_id
395
413
  @<%= name %>.delete_at(i)
414
+ <% if props.reference? && props.value(:containment) %>
415
+ val._set_container(nil, nil)
416
+ <% end %>
396
417
  <% if other_role %>
397
418
  val._unregister<%= firstToUpper(other_role) %>(self) unless val.is_a?(MMGeneric)
398
419
  <% end %>
@@ -401,7 +422,7 @@ module BuilderExtensions
401
422
  end
402
423
  end
403
424
 
404
- def <%= name %>=(val)
425
+ def set<%= firstToUpper(name) %>(val)
405
426
  return if val.nil?
406
427
  raise _assignmentTypeError(self, val, Enumerable) unless val.is_a? Enumerable
407
428
  get<%= firstToUpper(name) %>.each {|e|
@@ -411,15 +432,21 @@ module BuilderExtensions
411
432
  add<%= firstToUpper(name) %>(v)
412
433
  }
413
434
  end
414
- alias set<%= firstToUpper(name) %> <%= name %>=
435
+ alias <%= name %>= set<%= firstToUpper(name) %>
415
436
 
416
437
  def _register<%= firstToUpper(name) %>(val)
417
438
  @<%= name %> = [] unless @<%= name %>
418
439
  @<%= name %>.push val
440
+ <% if props.reference? && props.value(:containment) %>
441
+ val._set_container(self, :<%= name %>)
442
+ <% end %>
419
443
  end
420
444
 
421
445
  def _unregister<%= firstToUpper(name) %>(val)
422
446
  @<%= name %>.delete val
447
+ <% if props.reference? && props.value(:containment) %>
448
+ val._set_container(nil, nil)
449
+ <% end %>
423
450
  end
424
451
 
425
452
  CODE
@@ -435,7 +462,7 @@ module BuilderExtensions
435
462
  if (public_instance_methods+protected_instance_methods+private_instance_methods).include?(name)
436
463
  @@derived_builder ||= ERB.new <<-CODE
437
464
 
438
- def <%= name %>
465
+ def get<%= firstToUpper(name) %>
439
466
  raise "Derived feature requires public implementation of method <%= name %>_derived" \
440
467
  unless respond_to?(:<%= name+"_derived" %>)
441
468
  val = <%= name %>_derived
@@ -449,7 +476,9 @@ module BuilderExtensions
449
476
  <% end %>
450
477
  val
451
478
  end
452
- alias get<%= firstToUpper(name) %> <%= name %>
479
+ <% if name != "class" %>
480
+ alias <%= name %> get<%= firstToUpper(name) %>
481
+ <% end %>
453
482
  #TODO final_method :<%= name %>
454
483
 
455
484
  CODE
@@ -52,6 +52,32 @@ module BuilderRuntime
52
52
  result
53
53
  end
54
54
 
55
+ def eIsSet(role)
56
+ eval("defined? @#{role}") != nil
57
+ end
58
+
59
+ def eUnset(role)
60
+ if respond_to?("add#{firstToUpper(role.to_s)}")
61
+ setGeneric(role, [])
62
+ else
63
+ setGeneric(role, nil)
64
+ end
65
+ remove_instance_variable("@#{role}")
66
+ end
67
+
68
+ def eContainer
69
+ @_container
70
+ end
71
+
72
+ def eContainingFeature
73
+ @_containing_feature_name
74
+ end
75
+
76
+ def _set_container(container, containing_feature_name)
77
+ @_container = container
78
+ @_containing_feature_name = containing_feature_name
79
+ end
80
+
55
81
  def _assignmentTypeError(target, value, expected)
56
82
  text = ""
57
83
  if target
@@ -26,22 +26,37 @@ class FileCacheMap
26
26
 
27
27
  # load data associated with file +key_path+
28
28
  # returns :invalid in case either the associated file or the cache file has changed
29
- def load_data(key_path)
29
+ #
30
+ # options:
31
+ # :invalidation_reasons:
32
+ # an array which will receive symbols indicating why the cache is invalid:
33
+ # :no_cachefile, :cachefile_corrupted, :keyfile_changed
34
+ #
35
+ def load_data(key_path, options={})
36
+ reasons = options[:invalidation_reasons] || []
30
37
  cf = cache_file(key_path)
31
- return :invalid unless File.exist?(cf)
38
+ if !File.exist?(cf)
39
+ reasons << :no_cachefile
40
+ return :invalid
41
+ end
32
42
  result = nil
33
43
  File.open(cf, "rb") do |f|
34
44
  header = f.read(41)
35
- return :invalid unless header
45
+ if !header
46
+ reasons << :cachefile_corrupted
47
+ return :invalid
48
+ end
36
49
  checksum = header[0..39]
37
50
  data = f.read
38
51
  if calc_sha1(data) == checksum
39
52
  if calc_sha1_keydata(key_path) == data[0..39]
40
53
  result = data[41..-1]
41
54
  else
55
+ reasons << :keyfile_changed
42
56
  result = :invalid
43
57
  end
44
58
  else
59
+ reasons << :cachefile_corrupted
45
60
  result = :invalid
46
61
  end
47
62
  end
@@ -8,6 +8,7 @@ class ECoreToUML13 < RGen::Transformer
8
8
  def transform
9
9
  trans(:class => EPackage)
10
10
  trans(:class => EClass)
11
+ trans(:class => EEnum)
11
12
  end
12
13
 
13
14
  transform EPackage, :to => UML13::Package do
@@ -28,10 +29,22 @@ class ECoreToUML13 < RGen::Transformer
28
29
  }
29
30
  end
30
31
 
32
+ transform EEnum, :to => UML13::Class do
33
+ {:name => name,
34
+ :namespace => trans(ePackage),
35
+ :feature => trans(eLiterals)
36
+ }
37
+ end
38
+
39
+ transform EEnumLiteral, :to => UML13::Attribute do
40
+ {:name => name }
41
+ end
42
+
31
43
  transform EAttribute, :to => UML13::Attribute do
32
- _typemap = {EString => "string", EBoolean => "boolean", EInt => "int", EFloat => "float"}
44
+ _typemap = {"String" => "string", "Boolean" => "boolean", "Integer" => "int", "Float" => "float"}
33
45
  {:name => name,
34
- :taggedValue => [@env_out.new(UML13::TaggedValue, :tag => "type", :value => _typemap[eType] || "")]
46
+ :taggedValue => [@env_out.new(UML13::TaggedValue, :tag => "type",
47
+ :value => _typemap[eType.instanceClassName] || eType.name)]
35
48
  }
36
49
  end
37
50
 
@@ -63,4 +76,4 @@ class ECoreToUML13 < RGen::Transformer
63
76
  @model ||= @env_out.new(UML13::Model, :name => "Model")
64
77
  end
65
78
 
66
- end
79
+ end
@@ -142,6 +142,16 @@ class MetamodelBuilderTest < Test::Unit::TestCase
142
142
  abstract
143
143
  end
144
144
 
145
+ class ContainedClass < RGen::MetamodelBuilder::MMBase
146
+ end
147
+
148
+ class ContainerClass < RGen::MetamodelBuilder::MMBase
149
+ contains_one_uni 'oneChildUni', ContainedClass
150
+ contains_one 'oneChild', ContainedClass, 'parentOne'
151
+ contains_many_uni 'manyChildUni', ContainedClass
152
+ contains_many 'manyChild', ContainedClass, 'parentMany'
153
+ end
154
+
145
155
  end
146
156
 
147
157
  def mm
@@ -167,6 +177,10 @@ class MetamodelBuilderTest < Test::Unit::TestCase
167
177
  assert_equal 123, sc.integerWithDefault
168
178
  assert_equal 0.123, sc.floatWithDefault
169
179
  assert_equal true, sc.boolWithDefault
180
+
181
+ # setting nil should not make the default value appear on next read
182
+ sc.stringWithDefault = nil
183
+ assert_nil sc.stringWithDefault
170
184
 
171
185
  sc.anything = :asymbol
172
186
  assert_equal :asymbol, sc.anything
@@ -224,19 +238,20 @@ class MetamodelBuilderTest < Test::Unit::TestCase
224
238
  assert_equal ["a"], o.literals
225
239
  o.addLiterals("b")
226
240
  assert_equal ["a", "b"], o.literals
227
- # check for duplicates works by object identity, so there can be two strings "b"
228
241
  o.addLiterals("b")
229
242
  assert_equal ["a", "b", "b"], o.literals
230
- # but the same string object "a" can only occur once
243
+ # attributes allow the same object several times
231
244
  o.addLiterals(o.literals.first)
232
245
  assert_equal ["a", "b", "b", "a"], o.literals
246
+ assert o.literals[0].object_id == o.literals[3].object_id
233
247
  # removing works by object identity, so providing a new string won't delete an existing one
234
248
  o.removeLiterals("a")
235
249
  assert_equal ["a", "b", "b", "a"], o.literals
236
250
  theA = o.literals.first
251
+ # each remove command removes only one element: remove first "a"
237
252
  o.removeLiterals(theA)
238
253
  assert_equal ["b", "b", "a"], o.literals
239
- # removing something which is not present has no effect
254
+ # remove second "a" (same object)
240
255
  o.removeLiterals(theA)
241
256
  assert_equal ["b", "b"], o.literals
242
257
  o.removeLiterals(o.literals.first)
@@ -843,4 +858,264 @@ class MetamodelBuilderTest < Test::Unit::TestCase
843
858
  end
844
859
  end
845
860
 
861
+ def test_isset_set_to_nil
862
+ e = mm::SimpleClass.new
863
+ assert_respond_to e, :name
864
+ assert !e.eIsSet(:name)
865
+ assert !e.eIsSet("name")
866
+ e.name = nil
867
+ assert e.eIsSet(:name)
868
+ end
869
+
870
+ def test_isset_set_to_default
871
+ e = mm::SimpleClass.new
872
+ assert !e.eIsSet(:stringWithDefault)
873
+ # set the default value
874
+ e.name = "xtest"
875
+ assert e.eIsSet(:name)
876
+ end
877
+
878
+ def test_isset_many_add
879
+ e = mm::ManyAttrClass.new
880
+ assert_equal [], e.literals
881
+ assert !e.eIsSet(:literals)
882
+ e.addLiterals("x")
883
+ assert e.eIsSet(:literals)
884
+ end
885
+
886
+ def test_isset_many_remove
887
+ e = mm::ManyAttrClass.new
888
+ assert_equal [], e.literals
889
+ assert !e.eIsSet(:literals)
890
+ # removing a value which is not there
891
+ e.removeLiterals("x")
892
+ assert e.eIsSet(:literals)
893
+ end
894
+
895
+ def test_isset_ref
896
+ ac = mm::AClassOO.new
897
+ bc = mm::BClassOO.new
898
+ assert !bc.eIsSet(:aClass)
899
+ assert !ac.eIsSet(:bClass)
900
+ bc.aClass = ac
901
+ assert bc.eIsSet(:aClass)
902
+ assert ac.eIsSet(:bClass)
903
+ end
904
+
905
+ def test_isset_ref_many
906
+ ac = mm::AClassMM.new
907
+ bc = mm::BClassMM.new
908
+ assert !bc.eIsSet(:aClasses)
909
+ assert !ac.eIsSet(:bClasses)
910
+ bc.aClasses = [ac]
911
+ assert bc.eIsSet(:aClasses)
912
+ assert ac.eIsSet(:bClasses)
913
+ end
914
+
915
+ def test_unset_nil
916
+ e = mm::SimpleClass.new
917
+ e.name = nil
918
+ assert e.eIsSet(:name)
919
+ e.eUnset(:name)
920
+ assert !e.eIsSet(:name)
921
+ end
922
+
923
+ def test_unset_string
924
+ e = mm::SimpleClass.new
925
+ e.name = "someone"
926
+ assert e.eIsSet(:name)
927
+ e.eUnset(:name)
928
+ assert !e.eIsSet(:name)
929
+ end
930
+
931
+ def test_unset_ref
932
+ ac = mm::AClassOO.new
933
+ bc = mm::BClassOO.new
934
+ bc.aClass = ac
935
+ assert bc.eIsSet(:aClass)
936
+ assert ac.eIsSet(:bClass)
937
+ assert_equal bc, ac.bClass
938
+ bc.eUnset(:aClass)
939
+ assert_nil bc.aClass
940
+ assert_nil ac.bClass
941
+ assert !bc.eIsSet(:aClass)
942
+ # opposite ref is nil but still "set"
943
+ assert ac.eIsSet(:bClass)
944
+ end
945
+
946
+ def test_unset_ref_many
947
+ ac = mm::AClassMM.new
948
+ bc = mm::BClassMM.new
949
+ bc.aClasses = [ac]
950
+ assert bc.eIsSet(:aClasses)
951
+ assert ac.eIsSet(:bClasses)
952
+ assert_equal [bc], ac.bClasses
953
+ bc.eUnset(:aClasses)
954
+ assert_equal [], bc.aClasses
955
+ assert_equal [], ac.bClasses
956
+ assert !bc.eIsSet(:aClasses)
957
+ # opposite ref is empty but still "set"
958
+ assert ac.eIsSet(:bClasses)
959
+ end
960
+
961
+ def test_unset_marshal
962
+ e = mm::SimpleClass.new
963
+ e.name = "someone"
964
+ e.eUnset(:name)
965
+ e2 = Marshal.load(Marshal.dump(e))
966
+ assert e.object_id != e2.object_id
967
+ assert !e2.eIsSet(:name)
968
+ end
969
+
970
+ def test_conainer_one_uni
971
+ a = mm::ContainerClass.new
972
+ b = mm::ContainedClass.new
973
+ c = mm::ContainedClass.new
974
+ assert_nil b.eContainer
975
+ assert_nil b.eContainingFeature
976
+ a.oneChildUni = b
977
+ assert_equal a, b.eContainer
978
+ assert_equal :oneChildUni, b.eContainingFeature
979
+ a.oneChildUni = c
980
+ assert_nil b.eContainer
981
+ assert_nil b.eContainingFeature
982
+ assert_equal a, c.eContainer
983
+ assert_equal :oneChildUni, c.eContainingFeature
984
+ a.oneChildUni = nil
985
+ assert_nil c.eContainer
986
+ assert_nil c.eContainingFeature
987
+ end
988
+
989
+ def test_container_many_uni
990
+ a = mm::ContainerClass.new
991
+ b = mm::ContainedClass.new
992
+ c = mm::ContainedClass.new
993
+ a.addManyChildUni(b)
994
+ assert_equal a, b.eContainer
995
+ assert_equal :manyChildUni, b.eContainingFeature
996
+ a.addManyChildUni(c)
997
+ assert_equal a, c.eContainer
998
+ assert_equal :manyChildUni, c.eContainingFeature
999
+ a.removeManyChildUni(b)
1000
+ assert_nil b.eContainer
1001
+ assert_nil b.eContainingFeature
1002
+ assert_equal a, c.eContainer
1003
+ assert_equal :manyChildUni, c.eContainingFeature
1004
+ a.removeManyChildUni(c)
1005
+ assert_nil c.eContainer
1006
+ assert_nil c.eContainingFeature
1007
+ end
1008
+
1009
+ def test_conainer_one_bi
1010
+ a = mm::ContainerClass.new
1011
+ b = mm::ContainedClass.new
1012
+ c = mm::ContainerClass.new
1013
+ d = mm::ContainedClass.new
1014
+ a.oneChild = b
1015
+ assert_equal a, b.eContainer
1016
+ assert_equal :oneChild, b.eContainingFeature
1017
+ c.oneChild = d
1018
+ assert_equal c, d.eContainer
1019
+ assert_equal :oneChild, d.eContainingFeature
1020
+ a.oneChild = d
1021
+ assert_nil b.eContainer
1022
+ assert_nil b.eContainingFeature
1023
+ assert_equal a, d.eContainer
1024
+ assert_equal :oneChild, d.eContainingFeature
1025
+ end
1026
+
1027
+ def test_conainer_one_bi_rev
1028
+ a = mm::ContainerClass.new
1029
+ b = mm::ContainedClass.new
1030
+ c = mm::ContainerClass.new
1031
+ d = mm::ContainedClass.new
1032
+ a.oneChild = b
1033
+ assert_equal a, b.eContainer
1034
+ assert_equal :oneChild, b.eContainingFeature
1035
+ c.oneChild = d
1036
+ assert_equal c, d.eContainer
1037
+ assert_equal :oneChild, d.eContainingFeature
1038
+ d.parentOne = a
1039
+ assert_nil b.eContainer
1040
+ assert_nil b.eContainingFeature
1041
+ assert_equal a, d.eContainer
1042
+ assert_equal :oneChild, d.eContainingFeature
1043
+ end
1044
+
1045
+ def test_conainer_one_bi_nil
1046
+ a = mm::ContainerClass.new
1047
+ b = mm::ContainedClass.new
1048
+ a.oneChild = b
1049
+ assert_equal a, b.eContainer
1050
+ assert_equal :oneChild, b.eContainingFeature
1051
+ a.oneChild = nil
1052
+ assert_nil b.eContainer
1053
+ assert_nil b.eContainingFeature
1054
+ end
1055
+
1056
+ def test_conainer_one_bi_nil_rev
1057
+ a = mm::ContainerClass.new
1058
+ b = mm::ContainedClass.new
1059
+ a.oneChild = b
1060
+ assert_equal a, b.eContainer
1061
+ assert_equal :oneChild, b.eContainingFeature
1062
+ b.parentOne = nil
1063
+ assert_nil b.eContainer
1064
+ assert_nil b.eContainingFeature
1065
+ end
1066
+
1067
+ def test_container_many_bi
1068
+ a = mm::ContainerClass.new
1069
+ b = mm::ContainedClass.new
1070
+ c = mm::ContainedClass.new
1071
+ a.addManyChild(b)
1072
+ a.addManyChild(c)
1073
+ assert_equal a, b.eContainer
1074
+ assert_equal :manyChild, b.eContainingFeature
1075
+ assert_equal a, c.eContainer
1076
+ assert_equal :manyChild, c.eContainingFeature
1077
+ a.removeManyChild(b)
1078
+ assert_nil b.eContainer
1079
+ assert_nil b.eContainingFeature
1080
+ end
1081
+
1082
+ def test_conainer_many_bi_steal
1083
+ a = mm::ContainerClass.new
1084
+ b = mm::ContainedClass.new
1085
+ c = mm::ContainedClass.new
1086
+ d = mm::ContainerClass.new
1087
+ a.addManyChild(b)
1088
+ a.addManyChild(c)
1089
+ assert_equal a, b.eContainer
1090
+ assert_equal :manyChild, b.eContainingFeature
1091
+ assert_equal a, c.eContainer
1092
+ assert_equal :manyChild, c.eContainingFeature
1093
+ d.addManyChild(b)
1094
+ assert_equal d, b.eContainer
1095
+ assert_equal :manyChild, b.eContainingFeature
1096
+ end
1097
+
1098
+ def test_conainer_many_bi_steal_ref
1099
+ a = mm::ContainerClass.new
1100
+ b = mm::ContainedClass.new
1101
+ c = mm::ContainedClass.new
1102
+ d = mm::ContainerClass.new
1103
+ a.addManyChild(b)
1104
+ a.addManyChild(c)
1105
+ assert_equal a, b.eContainer
1106
+ assert_equal :manyChild, b.eContainingFeature
1107
+ assert_equal a, c.eContainer
1108
+ assert_equal :manyChild, c.eContainingFeature
1109
+ b.parentMany = d
1110
+ assert_equal d, b.eContainer
1111
+ assert_equal :manyChild, b.eContainingFeature
1112
+ end
1113
+
1114
+ def test_container_generic
1115
+ a = mm::ContainerClass.new
1116
+ assert_nothing_raised do
1117
+ a.oneChild = RGen::MetamodelBuilder::MMGeneric.new
1118
+ end
1119
+ end
1120
+
846
1121
  end