rgen 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +21 -0
- data/Project.yaml +22 -0
- data/Rakefile +21 -25
- data/lib/rgen/ecore/ecore.rb +7 -1
- data/lib/rgen/ecore/ecore_ext.rb +9 -1
- data/lib/rgen/ecore/ecore_to_json.rb +189 -0
- data/lib/rgen/ecore/ecore_to_ruby.rb +46 -10
- data/lib/rgen/fragment/fragmented_model.rb +2 -0
- data/lib/rgen/fragment/model_fragment.rb +3 -0
- data/lib/rgen/metamodel_builder/builder_extensions.rb +14 -6
- data/lib/rgen/metamodel_builder/builder_runtime.rb +12 -5
- data/lib/rgen/template_language/output_handler.rb +10 -0
- data/lib/rgen/template_language/template_container.rb +7 -3
- data/lib/rgen/template_language.rb +2 -1
- data/test/array_extensions_test.rb +7 -7
- data/test/ea_instantiator_test.rb +2 -2
- data/test/ea_serializer_test.rb +2 -2
- data/test/ecore_self_test.rb +2 -2
- data/test/ecore_to_ruby_test.rb +2 -2
- data/test/environment_test.rb +2 -2
- data/test/json_test.rb +4 -4
- data/test/metamodel_builder_test.rb +81 -46
- data/test/metamodel_from_ecore_test.rb +1 -1
- data/test/metamodel_order_test.rb +2 -2
- data/test/metamodel_roundtrip_test.rb +2 -2
- data/test/method_delegation_test.rb +5 -5
- data/test/model_builder/builder_context_test.rb +3 -3
- data/test/model_builder/builder_test.rb +11 -11
- data/test/model_builder/reference_resolver_test.rb +3 -3
- data/test/model_builder/serializer_test.rb +2 -2
- data/test/model_fragment_test.rb +2 -2
- data/test/output_handler_test.rb +2 -2
- data/test/qualified_name_provider_test.rb +2 -2
- data/test/qualified_name_resolver_test.rb +4 -4
- data/test/reference_resolver_test.rb +4 -4
- data/test/rgen_test.rb +1 -1
- data/test/template_language_test/templates/line_endings/mixed.tpl +6 -0
- data/test/template_language_test/templates/line_endings/unix.tpl +6 -0
- data/test/template_language_test/templates/line_endings/windows.tpl +6 -0
- data/test/template_language_test/templates/ws_test.tpl +21 -0
- data/test/template_language_test.rb +45 -8
- data/test/testmodel/class_model_checker.rb +17 -17
- data/test/testmodel/ecore_model_checker.rb +13 -13
- data/test/testmodel/object_model_checker.rb +6 -6
- data/test/transformer_test.rb +3 -3
- data/test/util/file_cache_map_test.rb +2 -2
- data/test/util/pattern_matcher_test.rb +7 -7
- data/test/xml_instantiator_test/simple_ecore_model_checker.rb +12 -12
- data/test/xml_instantiator_test.rb +8 -8
- metadata +106 -51
- data/test/coverage/assets/0.10.0/application.css +0 -799
- data/test/coverage/assets/0.10.0/application.js +0 -1707
- data/test/coverage/assets/0.10.0/colorbox/border.png +0 -0
- data/test/coverage/assets/0.10.0/colorbox/controls.png +0 -0
- data/test/coverage/assets/0.10.0/colorbox/loading.gif +0 -0
- data/test/coverage/assets/0.10.0/colorbox/loading_background.png +0 -0
- data/test/coverage/assets/0.10.0/favicon_green.png +0 -0
- data/test/coverage/assets/0.10.0/favicon_red.png +0 -0
- data/test/coverage/assets/0.10.0/favicon_yellow.png +0 -0
- data/test/coverage/assets/0.10.0/loading.gif +0 -0
- data/test/coverage/assets/0.10.0/magnify.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/test/coverage/index.html +0 -72
- data/test/metamodel_roundtrip_test/TestModel_Regenerated.rb +0 -71
- data/test/metamodel_roundtrip_test/houseMetamodel_Regenerated.ecore +0 -162
- data/test/metamodel_roundtrip_test/using_builtin_types_serialized.ecore +0 -9
- data/test/model_builder/ecore_internal.rb +0 -113
- data/test/testmodel/ea_testmodel_regenerated.xml +0 -813
- data/test/util/file_cache_map_test/testdir/fileA +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5091748f0290a5b0c82cf66e3bf2fea91ac774f6
|
4
|
+
data.tar.gz: db0663f172064272ed0bcd037e6715c12729429b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1355aa9282e5c3a18a93b65788f4fb5a4f92b26bb5cf89fa50e7ec71bd63dad090af06b73e292e959a7750fe08d75a5e0e4a5f0010fe84bb162c6eed1af338d1
|
7
|
+
data.tar.gz: 3f8755a969d35c22d4d8b3bcabeb6c75799b48b416d242a83530afbdc8b7364e682ba59750eddc375a454b450ef1ed5d32941951d7397430f4172d37aa1841a7
|
data/CHANGELOG
CHANGED
@@ -205,3 +205,24 @@
|
|
205
205
|
* Improved performance of setXXX and addXXX methods (pull request #22 from thallgren)
|
206
206
|
* Use a value larger than Fixnum max to test Bignum support (pull request #18 from graaff)
|
207
207
|
|
208
|
+
=0.8.1
|
209
|
+
|
210
|
+
* Improved performance of ECoreToRuby
|
211
|
+
* Fixed <%ws%> command to trigger indentation if starting a new line
|
212
|
+
|
213
|
+
=0.8.2
|
214
|
+
|
215
|
+
* Added helper methods
|
216
|
+
|
217
|
+
=0.8.3
|
218
|
+
|
219
|
+
* Performance improvement: getGeneric made a lot faster
|
220
|
+
|
221
|
+
=0.8.4
|
222
|
+
|
223
|
+
* Add early loading for types which have attributes conflicting with Ruby reserved words.
|
224
|
+
* Change type checking code to use ObjectSpace to find class objects. This is to find classes with an unbound name.
|
225
|
+
|
226
|
+
=0.9.0
|
227
|
+
|
228
|
+
* Update to support Ruby 2.7, drop support for older Rubies
|
data/Project.yaml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
name: rgen
|
2
|
+
gemspec: rgen.gemspec
|
3
|
+
git: https://github.com/mthiede/rgen.git
|
4
|
+
version: 0.9.0
|
5
|
+
summary: Ruby Modelling and Generator Framework
|
6
|
+
email: martin dot thiede at gmx de
|
7
|
+
homepage: http://ruby-gen.org
|
8
|
+
rubyforge_project: rgen
|
9
|
+
description: 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.
|
10
|
+
authors: [Martin Thiede]
|
11
|
+
rdoc_options: [--main, README.rdoc, -x, test, -x, metamodels, -x, ea_support/uml13*]
|
12
|
+
extra_rdoc_files: [README.rdoc, CHANGELOG, MIT-LICENSE]
|
13
|
+
include_files: ['lib/**/*', 'test/**/*', README.rdoc, CHANGELOG, MIT-LICENSE, Rakefile]
|
14
|
+
exclude_files: ['**/*.bak']
|
15
|
+
encrypt_sources: false
|
16
|
+
dependencies:
|
17
|
+
https://rubygems.org:
|
18
|
+
- {name: nokogiri, version: ['>= 1.11.2', '< 1.12'], development: true}
|
19
|
+
- {name: rake, version: '~> 12.0', development: true}
|
20
|
+
- {name: minitest, version: ['~> 5.0', '>= 5.10.1'], development: true}
|
21
|
+
- {name: minitest-fail-fast, version: '~> 0.1.0', development: true}
|
22
|
+
- {name: andand, version: '1.3.3', development: true}
|
data/Rakefile
CHANGED
@@ -1,41 +1,37 @@
|
|
1
1
|
require 'rubygems/package_task'
|
2
2
|
require 'rdoc/task'
|
3
|
+
require 'rake/testtask'
|
3
4
|
|
4
|
-
RGenGemSpec =
|
5
|
-
s.name = %q{rgen}
|
6
|
-
s.version = "0.8.0"
|
7
|
-
s.date = Time.now.strftime("%Y-%m-%d")
|
8
|
-
s.summary = %q{Ruby Modelling and Generator Framework}
|
9
|
-
s.email = %q{martin dot thiede at gmx de}
|
10
|
-
s.homepage = %q{http://ruby-gen.org}
|
11
|
-
s.rubyforge_project = %q{rgen}
|
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
|
-
s.authors = ["Martin Thiede"]
|
14
|
-
gemfiles = Rake::FileList.new
|
15
|
-
gemfiles.include("{lib,test}/**/*")
|
16
|
-
gemfiles.include("README.rdoc", "CHANGELOG", "MIT-LICENSE", "Rakefile")
|
17
|
-
gemfiles.exclude(/\b\.bak\b/)
|
18
|
-
s.files = gemfiles
|
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
|
-
end
|
5
|
+
RGenGemSpec = eval(File.read('rgen.gemspec'))
|
22
6
|
|
23
7
|
RDoc::Task.new do |rd|
|
24
|
-
rd.main =
|
25
|
-
rd.rdoc_files.include(
|
26
|
-
rd.rdoc_files.exclude(
|
27
|
-
rd.rdoc_files.exclude(
|
28
|
-
rd.rdoc_dir =
|
8
|
+
rd.main = 'README.rdoc'
|
9
|
+
rd.rdoc_files.include('README.rdoc', 'CHANGELOG', 'MIT-LICENSE', 'lib/**/*.rb')
|
10
|
+
rd.rdoc_files.exclude('lib/metamodels/*')
|
11
|
+
rd.rdoc_files.exclude('lib/ea_support/uml13*')
|
12
|
+
rd.rdoc_dir = 'doc'
|
29
13
|
end
|
30
14
|
|
31
15
|
RGenPackageTask = Gem::PackageTask.new(RGenGemSpec) do |p|
|
32
16
|
p.need_zip = false
|
33
|
-
end
|
17
|
+
end
|
18
|
+
|
19
|
+
::Rake::TestTask.new(:test) do |t|
|
20
|
+
t.test_files = ['test/rgen_test.rb']
|
21
|
+
t.warning = false
|
22
|
+
end
|
34
23
|
|
35
24
|
task :prepare_package_rdoc => :rdoc do
|
36
|
-
RGenPackageTask.package_files.include(
|
25
|
+
RGenPackageTask.package_files.include('doc/**/*')
|
37
26
|
end
|
38
27
|
|
39
28
|
task :release => [:prepare_package_rdoc, :package]
|
40
29
|
|
41
30
|
task :clobber => [:clobber_rdoc, :clobber_package]
|
31
|
+
|
32
|
+
task :ecore_to_json do
|
33
|
+
require 'rgen/ecore/ecore_to_json'
|
34
|
+
|
35
|
+
exporter = RGen::ECore::ECoreToJson.new
|
36
|
+
File.write('ecore.json', exporter.epackage_to_json_string(RGen.ecore, exporter.ecore_datatypes))
|
37
|
+
end
|
data/lib/rgen/ecore/ecore.rb
CHANGED
@@ -12,9 +12,11 @@ module RGen
|
|
12
12
|
extend RGen::MetamodelBuilder::ModuleExtension
|
13
13
|
|
14
14
|
class EObject < RGen::MetamodelBuilder::MMBase
|
15
|
+
abstract
|
15
16
|
end
|
16
17
|
|
17
18
|
class EModelElement < RGen::MetamodelBuilder::MMBase
|
19
|
+
abstract
|
18
20
|
end
|
19
21
|
|
20
22
|
class EAnnotation < RGen::MetamodelBuilder::MMMultiple(EModelElement, EObject)
|
@@ -22,10 +24,12 @@ module RGen
|
|
22
24
|
end
|
23
25
|
|
24
26
|
class ENamedElement < EModelElement
|
27
|
+
abstract
|
25
28
|
has_attr 'name', String
|
26
29
|
end
|
27
30
|
|
28
31
|
class ETypedElement < ENamedElement
|
32
|
+
abstract
|
29
33
|
has_attr 'lowerBound', Integer, :defaultValueLiteral => "0"
|
30
34
|
has_attr 'ordered', Boolean, :defaultValueLiteral => "true"
|
31
35
|
has_attr 'unique', Boolean, :defaultValueLiteral => "true"
|
@@ -43,6 +47,7 @@ module RGen
|
|
43
47
|
end
|
44
48
|
|
45
49
|
class EStructuralFeature < ETypedElement
|
50
|
+
abstract
|
46
51
|
has_attr 'changeable', Boolean, :defaultValueLiteral => "true"
|
47
52
|
has_attr 'defaultValue', Object, :derived=>true
|
48
53
|
has_attr 'defaultValueLiteral', String
|
@@ -76,6 +81,7 @@ module RGen
|
|
76
81
|
end
|
77
82
|
|
78
83
|
class EClassifier < ENamedElement
|
84
|
+
abstract
|
79
85
|
has_attr 'defaultValue', Object, :derived=>true
|
80
86
|
has_attr 'instanceClass', Object, :derived=>true
|
81
87
|
has_attr 'instanceClassName', String
|
@@ -155,7 +161,7 @@ module RGen
|
|
155
161
|
has_many 'eAttributes', ECore::EAttribute, :derived=>true
|
156
162
|
has_many 'eReferences', ECore::EReference, :derived=>true
|
157
163
|
|
158
|
-
module ClassModule
|
164
|
+
module ClassModule
|
159
165
|
def eAllAttributes_derived
|
160
166
|
eAttributes + eSuperTypes.eAllAttributes
|
161
167
|
end
|
data/lib/rgen/ecore/ecore_ext.rb
CHANGED
@@ -63,7 +63,15 @@ module RGen
|
|
63
63
|
def eAllSubTypes
|
64
64
|
eSubTypes + eSubTypes.eAllSubTypes
|
65
65
|
end
|
66
|
+
|
67
|
+
def concrete
|
68
|
+
!(abstract || interface)
|
69
|
+
end
|
70
|
+
|
71
|
+
def isAssignableFrom(cls)
|
72
|
+
cls == self || cls.eAllSuperTypes.any? { |super_type| super_type == self }
|
73
|
+
end
|
66
74
|
|
67
|
-
|
75
|
+
end
|
68
76
|
end
|
69
77
|
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'rgen/ecore/ecore'
|
2
|
+
require 'json'
|
3
|
+
require 'andand'
|
4
|
+
|
5
|
+
module RGen
|
6
|
+
|
7
|
+
module ECore
|
8
|
+
|
9
|
+
# ECoreToJson can turn ECore models into their JSON metamodel representations
|
10
|
+
class ECoreToJson
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def root_elements_to_json_string(root_elements)
|
17
|
+
JSON.pretty_generate(root_elements.map do |el|
|
18
|
+
if el.is_a?(RGen::ECore::EPackage)
|
19
|
+
epackage(el)
|
20
|
+
elsif el.is_a?(RGen::ECore::EClass)
|
21
|
+
eclass(el)
|
22
|
+
else
|
23
|
+
raise "Not implemented for #{el}"
|
24
|
+
end
|
25
|
+
end)
|
26
|
+
end
|
27
|
+
|
28
|
+
def epackage_to_json(package)
|
29
|
+
epackage(package)
|
30
|
+
end
|
31
|
+
|
32
|
+
def ecore_datatypes
|
33
|
+
[RGen::ECore::EString, RGen::ECore::EInt, RGen::ECore::ELong, RGen::ECore::EBoolean, RGen::ECore::EFloat,
|
34
|
+
RGen::ECore::ERubyObject, RGen::ECore::EJavaObject, RGen::ECore::ERubyClass, RGen::ECore::EJavaClass]
|
35
|
+
.map {|dt| edatatype(dt)}
|
36
|
+
end
|
37
|
+
|
38
|
+
def epackage_to_json_pretty_string(package, append = [])
|
39
|
+
JSON.pretty_generate([epackage_to_json(package)] + append)
|
40
|
+
end
|
41
|
+
|
42
|
+
def epackage_to_json_string(package, append = [])
|
43
|
+
JSON.generate([epackage_to_json(package)] + append)
|
44
|
+
end
|
45
|
+
|
46
|
+
def emodelelement(me)
|
47
|
+
{
|
48
|
+
:eAnnotations => me.eAnnotations.map { |e| eannotation(e) }
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def enamedelement(ne)
|
54
|
+
merge(emodelelement(ne), {:name => ne.name})
|
55
|
+
end
|
56
|
+
|
57
|
+
def epackage(package)
|
58
|
+
merge(enamedelement(package), {
|
59
|
+
:_class_ref => 'RGen.ECore.EPackage',
|
60
|
+
:eClassifiers => package.eClassifiers.map do |classifier|
|
61
|
+
if classifier.is_a?(RGen::ECore::EClass)
|
62
|
+
eclass(classifier)
|
63
|
+
elsif classifier.is_a?(RGen::ECore::EEnum)
|
64
|
+
eenum(classifier)
|
65
|
+
else
|
66
|
+
edatatype(classifier)
|
67
|
+
end
|
68
|
+
end,
|
69
|
+
:eSubpackages => package.eSubpackages.map { |sp| epackage(sp) },
|
70
|
+
:nsURI => package.nsURI,
|
71
|
+
:nsPrefix => package.nsPrefix
|
72
|
+
})
|
73
|
+
end
|
74
|
+
|
75
|
+
def eclassifier(classifier)
|
76
|
+
enamedelement(classifier).merge({
|
77
|
+
# omit :instanceClassName => classifier.instanceClassName
|
78
|
+
})
|
79
|
+
end
|
80
|
+
|
81
|
+
def eclass(_class)
|
82
|
+
merge(eclassifier(_class), {
|
83
|
+
:_class_ref => 'RGen.ECore.EClass',
|
84
|
+
:abstract => _class.abstract,
|
85
|
+
:interface => _class.interface,
|
86
|
+
:eStructuralFeatures => _class.eStructuralFeatures.map do |sf|
|
87
|
+
if sf.is_a?(RGen::ECore::EReference)
|
88
|
+
ereference(sf)
|
89
|
+
else
|
90
|
+
eattribute(sf)
|
91
|
+
end
|
92
|
+
end,
|
93
|
+
:eSuperTypes => _class.eSuperTypes.map { |st| {:_ref => ref_id(st)} }
|
94
|
+
})
|
95
|
+
end
|
96
|
+
|
97
|
+
def edatatype(_datatype)
|
98
|
+
merge(eclassifier(_datatype), {
|
99
|
+
:_class_ref => 'RGen.ECore.EDataType',
|
100
|
+
:serializable => _datatype.serializable,
|
101
|
+
:instanceClassName => _datatype.instanceClassName
|
102
|
+
})
|
103
|
+
end
|
104
|
+
|
105
|
+
def eenum(enum)
|
106
|
+
merge(edatatype(enum), {
|
107
|
+
:_class_ref => 'RGen.ECore.EEnum',
|
108
|
+
:eLiterals => enum.eLiterals.map do |l|
|
109
|
+
merge(enamedelement(l), {
|
110
|
+
:_class_ref => 'RGen.ECore.EEnumLiteral',
|
111
|
+
:value => l.value,
|
112
|
+
})
|
113
|
+
end
|
114
|
+
})
|
115
|
+
end
|
116
|
+
|
117
|
+
def eannotation(e)
|
118
|
+
merge(emodelelement(e), {
|
119
|
+
:_class_ref => 'RGen.ECore.EAnnotation',
|
120
|
+
:source => e.source,
|
121
|
+
:details => e.details.map do |d|
|
122
|
+
merge({}, {
|
123
|
+
:_class_ref => 'RGen.ECore.EStringToStringMapEntry',
|
124
|
+
:key => d.key,
|
125
|
+
:value => d.value
|
126
|
+
})
|
127
|
+
end
|
128
|
+
})
|
129
|
+
end
|
130
|
+
|
131
|
+
def etypedelement(te)
|
132
|
+
merge(enamedelement(te), {
|
133
|
+
:ordered => te.ordered,
|
134
|
+
:unique => te.unique,
|
135
|
+
:lowerBound => te.lowerBound,
|
136
|
+
:upperBound => te.upperBound,
|
137
|
+
:many => te.many,
|
138
|
+
:required => te.required,
|
139
|
+
:eType => {:_ref => te.eType ? ref_id(te.eType) : nil}
|
140
|
+
})
|
141
|
+
end
|
142
|
+
|
143
|
+
def estructuralfeature(sf)
|
144
|
+
merge(etypedelement(sf), {
|
145
|
+
:changeable => sf.changeable,
|
146
|
+
:volatile => sf.volatile,
|
147
|
+
:transient => sf.transient,
|
148
|
+
:defaultValueLiteral => sf.defaultValueLiteral,
|
149
|
+
:unsettable => sf.unsettable,
|
150
|
+
:derived => sf.derived,
|
151
|
+
})
|
152
|
+
end
|
153
|
+
|
154
|
+
def eattribute(attr)
|
155
|
+
merge(estructuralfeature(attr), {
|
156
|
+
:_class_ref => 'RGen.ECore.EAttribute',
|
157
|
+
:iD => attr.iD
|
158
|
+
})
|
159
|
+
end
|
160
|
+
|
161
|
+
def ereference(ref)
|
162
|
+
merge(estructuralfeature(ref), {
|
163
|
+
:_class_ref => 'RGen.ECore.EReference',
|
164
|
+
:containment => ref.containment,
|
165
|
+
:resolveProxies => ref.resolveProxies,
|
166
|
+
:eOpposite => ref.eOpposite ? {:_ref => "#{ref_id(ref.eOpposite.eContainer)}.#{ref.eOpposite.name}"} : nil
|
167
|
+
})
|
168
|
+
end
|
169
|
+
|
170
|
+
def ref_id(obj)
|
171
|
+
res = ref_parts(obj)
|
172
|
+
res.join('.')
|
173
|
+
end
|
174
|
+
|
175
|
+
def ref_parts(obj)
|
176
|
+
return [obj.name] unless obj.andand.eContainer
|
177
|
+
ref_parts(obj.eContainer) << obj.name
|
178
|
+
end
|
179
|
+
|
180
|
+
def merge(hash, values)
|
181
|
+
values.each { |k, v| hash[k] = v unless v.nil? }
|
182
|
+
hash
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'set'
|
1
2
|
require 'rgen/ecore/ecore'
|
2
3
|
|
3
4
|
module RGen
|
@@ -11,6 +12,7 @@ class ECoreToRuby
|
|
11
12
|
@modules = {}
|
12
13
|
@classifiers = {}
|
13
14
|
@features_added = {}
|
15
|
+
@reserved = Set.new(Object.methods)
|
14
16
|
end
|
15
17
|
|
16
18
|
# Create a Ruby module representing +epackage+.
|
@@ -38,22 +40,35 @@ class ECoreToRuby
|
|
38
40
|
# of a class/module with a temporary name is queried.
|
39
41
|
#
|
40
42
|
def create_module(epackage, under=Module.new)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
with_empty_constant_order_helper do
|
44
|
+
temp = under.to_s.start_with?("#")
|
45
|
+
mod = create_module_internal(epackage, under, temp)
|
46
|
+
|
47
|
+
epackage.eAllClassifiers.each do |c|
|
48
|
+
if c.is_a?(RGen::ECore::EClass)
|
49
|
+
create_class(c, temp)
|
50
|
+
elsif c.is_a?(RGen::ECore::EEnum)
|
51
|
+
create_enum(c)
|
52
|
+
end
|
49
53
|
end
|
50
|
-
end
|
51
54
|
|
52
|
-
|
55
|
+
load_classes_with_reserved_keywords(epackage)
|
56
|
+
mod
|
57
|
+
end
|
53
58
|
end
|
54
59
|
|
55
60
|
private
|
56
61
|
|
62
|
+
def load_classes_with_reserved_keywords(epackage)
|
63
|
+
epackage.eAllClassifiers.each do |eclass|
|
64
|
+
# we early load classes which have ruby reserved keywords
|
65
|
+
if eclass.is_a?(RGen::ECore::EClass)
|
66
|
+
reserved_used = eclass.eStructuralFeatures.any? { |f| @reserved.include?(f.name.to_sym) }
|
67
|
+
add_features(eclass) if reserved_used
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
57
72
|
def create_module_internal(epackage, under, temp)
|
58
73
|
return @modules[epackage] if @modules[epackage]
|
59
74
|
|
@@ -199,6 +214,27 @@ class ECoreToRuby
|
|
199
214
|
end
|
200
215
|
end
|
201
216
|
|
217
|
+
class EmptyConstantOrderHelper
|
218
|
+
def classCreated(c); end
|
219
|
+
def moduleCreated(m); end
|
220
|
+
def enumCreated(e); end
|
221
|
+
end
|
222
|
+
|
223
|
+
def with_empty_constant_order_helper
|
224
|
+
orig_coh = RGen::MetamodelBuilder::ConstantOrderHelper
|
225
|
+
RGen::MetamodelBuilder.instance_eval { remove_const(:ConstantOrderHelper) }
|
226
|
+
RGen::MetamodelBuilder.const_set(:ConstantOrderHelper, EmptyConstantOrderHelper.new)
|
227
|
+
|
228
|
+
begin
|
229
|
+
result = yield
|
230
|
+
ensure
|
231
|
+
RGen::MetamodelBuilder.instance_eval { remove_const(:ConstantOrderHelper) }
|
232
|
+
RGen::MetamodelBuilder.const_set(:ConstantOrderHelper, orig_coh)
|
233
|
+
end
|
234
|
+
|
235
|
+
result
|
236
|
+
end
|
237
|
+
|
202
238
|
public
|
203
239
|
|
204
240
|
def add_features(eclass)
|
@@ -111,6 +111,8 @@ class FragmentedModel
|
|
111
111
|
# This is a Hash mapping identifiers to model elements accessible via the identifier.
|
112
112
|
#
|
113
113
|
def index
|
114
|
+
# Invalidate the cache when any fragment's local index changes.
|
115
|
+
# Assumption: If the local index content changes, there is a new index object.
|
114
116
|
fragments.each do |f|
|
115
117
|
if !@fragment_index[f] || (@fragment_index[f].object_id != f.index.object_id)
|
116
118
|
@fragment_index[f] = f.index
|
@@ -117,6 +117,9 @@ class ModelFragment
|
|
117
117
|
end
|
118
118
|
|
119
119
|
# Returns the index of the element contained in this fragment.
|
120
|
+
#
|
121
|
+
# FragmentedModel's index caching depends on the fact that any change
|
122
|
+
# of a fragment's index contents implies a new index object.
|
120
123
|
#
|
121
124
|
def index
|
122
125
|
build_index unless @index
|
@@ -319,6 +319,10 @@ module BuilderExtensions
|
|
319
319
|
end
|
320
320
|
<% if name != "class" %>
|
321
321
|
alias <%= name %> get<%= firstToUpper(name) %>
|
322
|
+
<% else %>
|
323
|
+
def getGeneric(role)
|
324
|
+
send("get\#{firstToUpper(role.to_s)}")
|
325
|
+
end
|
322
326
|
<% end %>
|
323
327
|
|
324
328
|
CODE
|
@@ -380,10 +384,14 @@ module BuilderExtensions
|
|
380
384
|
@@many_read_builder ||= ERB.new <<-CODE
|
381
385
|
|
382
386
|
def get<%= firstToUpper(name) %>
|
383
|
-
( @<%= name %> ? @<%= name %>.dup : [] )
|
387
|
+
( defined?(@<%= name %>) ? @<%= name %>.dup : [] )
|
384
388
|
end
|
385
389
|
<% if name != "class" %>
|
386
390
|
alias <%= name %> get<%= firstToUpper(name) %>
|
391
|
+
<% else %>
|
392
|
+
def getGeneric(role)
|
393
|
+
send("get\#{firstToUpper(role.to_s)}")
|
394
|
+
end
|
387
395
|
<% end %>
|
388
396
|
|
389
397
|
CODE
|
@@ -394,7 +402,7 @@ module BuilderExtensions
|
|
394
402
|
@@many_write_builder ||= ERB.new <<-CODE
|
395
403
|
|
396
404
|
def add<%= firstToUpper(name) %>(val, index=-1)
|
397
|
-
@<%= name %> = [] unless @<%= name %>
|
405
|
+
@<%= name %> = [] unless defined?(@<%= name %>)
|
398
406
|
return if val.nil? || (val.is_a?(MMBase) || val.is_a?(MMGeneric)) && @<%= name %>.any? {|e| e.equal?(val)}
|
399
407
|
<%= type_check_code("val", props) %>
|
400
408
|
@<%= name %>.insert(index, val)
|
@@ -407,7 +415,7 @@ module BuilderExtensions
|
|
407
415
|
end
|
408
416
|
|
409
417
|
def remove<%= firstToUpper(name) %>(val)
|
410
|
-
@<%= name %> = [] unless @<%= name %>
|
418
|
+
@<%= name %> = [] unless defined?(@<%= name %>)
|
411
419
|
@<%= name %>.each_with_index do |e,i|
|
412
420
|
if e.equal?(val)
|
413
421
|
@<%= name %>.delete_at(i)
|
@@ -428,7 +436,7 @@ module BuilderExtensions
|
|
428
436
|
get<%= firstToUpper(name) %>.each {|e|
|
429
437
|
remove<%= firstToUpper(name) %>(e)
|
430
438
|
}
|
431
|
-
@<%= name %> = [] unless @<%= name %>
|
439
|
+
@<%= name %> = [] unless defined?(@<%= name %>)
|
432
440
|
<% if props.reference? %>
|
433
441
|
val.uniq {|elem| elem.object_id }.each {|elem|
|
434
442
|
next if elem.nil?
|
@@ -451,7 +459,7 @@ module BuilderExtensions
|
|
451
459
|
alias <%= name %>= set<%= firstToUpper(name) %>
|
452
460
|
|
453
461
|
def _register<%= firstToUpper(name) %>(val)
|
454
|
-
@<%= name %> = [] unless @<%= name %>
|
462
|
+
@<%= name %> = [] unless defined?(@<%= name %>)
|
455
463
|
@<%= name %>.push val
|
456
464
|
<% if props.reference? && props.value(:containment) %>
|
457
465
|
val._set_container(self, :<%= name %>)
|
@@ -531,7 +539,7 @@ module BuilderExtensions
|
|
531
539
|
code << "\n"
|
532
540
|
expected = "Integer"
|
533
541
|
elsif props.impl_type.is_a?(Class)
|
534
|
-
code << "unless #{varname}.nil? || #{varname}.is_a?(#{props.impl_type}) || #{varname}.is_a?(MMGeneric)"
|
542
|
+
code << "unless #{varname}.nil? || #{varname}.is_a?(ObjectSpace._id2ref(#{props.impl_type.object_id})) || #{varname}.is_a?(MMGeneric)"
|
535
543
|
code << " || #{varname}.is_a?(BigDecimal)" if props.impl_type == Float && defined?(BigDecimal)
|
536
544
|
code << "\n"
|
537
545
|
expected = props.impl_type.to_s
|
@@ -58,14 +58,17 @@ module BuilderRuntime
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
|
62
|
-
send("get#{firstToUpper(role.to_s)}")
|
63
|
-
end
|
61
|
+
alias getGeneric send
|
64
62
|
|
65
63
|
def getGenericAsArray(role)
|
66
64
|
result = getGeneric(role)
|
67
|
-
|
68
|
-
|
65
|
+
if result.nil?
|
66
|
+
[]
|
67
|
+
elsif result.is_a?(Array)
|
68
|
+
result
|
69
|
+
else
|
70
|
+
[result]
|
71
|
+
end
|
69
72
|
end
|
70
73
|
|
71
74
|
def eIsSet(role)
|
@@ -100,6 +103,10 @@ module BuilderRuntime
|
|
100
103
|
|
101
104
|
# if a block is given, calls the block on every contained element in depth first order.
|
102
105
|
# if the block returns :prune, recursion will stop at this point.
|
106
|
+
#
|
107
|
+
# BEWARE of concurrent modification of contained elements while iterating!
|
108
|
+
# (adding/removing containers or contained elements)
|
109
|
+
# if you need to do such modifications, use the variant without a block instead.
|
103
110
|
#
|
104
111
|
# if no block is given builds and returns a list of all contained elements.
|
105
112
|
#
|
@@ -91,6 +91,16 @@ module TemplateLanguage
|
|
91
91
|
@output.concat(s)
|
92
92
|
end
|
93
93
|
|
94
|
+
def direct_concat_allow_indent(s)
|
95
|
+
unless @noIndentNextLine || (@output[-1] && @output[-1] != NL_CHAR)
|
96
|
+
@output.concat(@indent_string)
|
97
|
+
else
|
98
|
+
@noIndentNextLine = false
|
99
|
+
end
|
100
|
+
@state = :wait_for_nl
|
101
|
+
@output.concat(s)
|
102
|
+
end
|
103
|
+
|
94
104
|
def ignoreNextNL
|
95
105
|
@ignoreNextNL = true
|
96
106
|
end
|
@@ -84,7 +84,7 @@ module RGen
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def ws
|
87
|
-
_direct_concat(" ")
|
87
|
+
_direct_concat(" ", true)
|
88
88
|
end
|
89
89
|
|
90
90
|
def iinc
|
@@ -210,9 +210,13 @@ module RGen
|
|
210
210
|
raise StandardError.new("Template class not matching: #{tpl} for #{context.class.name}") unless found
|
211
211
|
end
|
212
212
|
|
213
|
-
def _direct_concat(s)
|
213
|
+
def _direct_concat(s, allow_indent=false)
|
214
214
|
if @output.is_a? OutputHandler
|
215
|
-
|
215
|
+
if allow_indent
|
216
|
+
@output.direct_concat_allow_indent(s)
|
217
|
+
else
|
218
|
+
@output.direct_concat(s)
|
219
|
+
end
|
216
220
|
else
|
217
221
|
@output << s
|
218
222
|
end
|
@@ -129,6 +129,7 @@ module RGen
|
|
129
129
|
# Starting from this point one can add indentation and newlines as required by using
|
130
130
|
# explicit formatting commands:
|
131
131
|
# * <code><%nl%></code> (newline) starts a new line
|
132
|
+
# * <code><%ws%></code> (whitespace) adds an explicit space
|
132
133
|
# * <code><%iinc%></code> (indentation increment) increases the current indentation
|
133
134
|
# * <code><%idec%></code> (indentation decrement) decreases the current indentation
|
134
135
|
# * <code><%nonl%></code> (no newline) ignore next newline
|
@@ -294,4 +295,4 @@ module TemplateLanguage
|
|
294
295
|
|
295
296
|
end
|
296
297
|
|
297
|
-
end
|
298
|
+
end
|