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 +10 -0
- data/README.rdoc +78 -0
- data/Rakefile +13 -17
- data/lib/rgen/fragment/model_fragment.rb +1 -0
- data/lib/rgen/metamodel_builder.rb +3 -0
- data/lib/rgen/metamodel_builder/builder_extensions.rb +41 -12
- data/lib/rgen/metamodel_builder/builder_runtime.rb +26 -0
- data/lib/rgen/util/file_cache_map.rb +18 -3
- data/lib/transformers/ecore_to_uml13.rb +16 -3
- data/test/metamodel_builder_test.rb +278 -3
- data/test/model_builder/ecore_internal.rb +8 -8
- data/test/model_fragment_test.rb +30 -0
- data/test/rgen_test.rb +1 -0
- data/test/testmodel/ea_testmodel_regenerated.xml +583 -583
- data/test/util/file_cache_map_test.rb +12 -4
- data/test/util/pattern_matcher_test.rb +97 -0
- data/test/util_test.rb +1 -0
- metadata +9 -7
- data/README +0 -76
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 '
|
2
|
-
require '
|
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.
|
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
|
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
|
-
|
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 =
|
32
|
-
p.need_zip =
|
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
|
@@ -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
|
315
|
+
(defined? @<%= name %>) ? @<%= name %> : <%= defVal %>
|
316
316
|
<% else %>
|
317
317
|
@<%= name %>
|
318
318
|
<% end %>
|
319
319
|
end
|
320
|
-
|
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
|
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) %>
|
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
|
-
|
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
|
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) %>
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 = {
|
44
|
+
_typemap = {"String" => "string", "Boolean" => "boolean", "Integer" => "int", "Float" => "float"}
|
33
45
|
{:name => name,
|
34
|
-
:taggedValue => [@env_out.new(UML13::TaggedValue, :tag => "type",
|
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
|
-
#
|
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
|
-
#
|
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
|