rgen 0.7.0 → 0.8.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +27 -0
- data/Project.yaml +21 -0
- data/README.rdoc +1 -1
- data/Rakefile +22 -25
- data/lib/rgen/ecore/ecore.rb +1 -1
- data/lib/rgen/ecore/ecore_ext.rb +9 -1
- data/lib/rgen/ecore/ecore_to_json.rb +188 -0
- data/lib/rgen/ecore/ecore_to_ruby.rb +146 -47
- data/lib/rgen/fragment/fragmented_model.rb +2 -0
- data/lib/rgen/fragment/model_fragment.rb +3 -0
- data/lib/rgen/instantiator/default_xml_instantiator.rb +93 -88
- data/lib/rgen/metamodel_builder/builder_extensions.rb +33 -9
- data/lib/rgen/metamodel_builder/builder_runtime.rb +12 -5
- data/lib/rgen/template_language/output_handler.rb +52 -19
- data/lib/rgen/template_language/template_container.rb +17 -7
- 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 +73 -0
- data/test/environment_test.rb +2 -2
- data/test/json_test.rb +4 -4
- data/test/metamodel_builder_test.rb +79 -44
- 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 +2 -1
- data/test/template_language_test/templates/indent_nonl_at_eof_test/test.tpl +14 -0
- data/test/template_language_test/templates/indent_same_line_sub/test.tpl +16 -0
- 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 +60 -9
- 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 +93 -22
- 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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e58b57346e1f7e95fcaa15f29112706c911d20ed
|
4
|
+
data.tar.gz: 6551cb4e9579f7e76582018876973edd9a58d0e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e82e58dd4eaf95de47ef1714a778558a6bd3cb76f8229fb43e029a98f9e03c6234ee2fab831adde1d7de1b953665afab031f27f39b0ad7a060a91c4ed7c7328
|
7
|
+
data.tar.gz: 47b73a00783a82d630b0771fb55b01c4da6adffe73a459cd35828dd5040644b8b0f6cd00a565a4abf257d8c4d2e97ca17db2c072cbe05e8ae44fe9b2b3a2637e
|
data/CHANGELOG
CHANGED
@@ -195,3 +195,30 @@
|
|
195
195
|
* Added setNilOrRemoveGeneric and setNilOrRemoveAllGeneric methods
|
196
196
|
* Added disconnectContainer method
|
197
197
|
|
198
|
+
=0.8.0
|
199
|
+
|
200
|
+
* Fixed missing indentation when template file is not terminated by a newline
|
201
|
+
* Fixed missing indentation when expand in same line expands sub templates
|
202
|
+
* Fixed DefaultXMLInstantiator naming error with a tag named 'File' (issue #19, pull request #21 from jkugs)
|
203
|
+
* Simplified ECoreToRuby and optionally let it create modules with non-temporary names
|
204
|
+
* Improved performance of output handler
|
205
|
+
* Improved performance of setXXX and addXXX methods (pull request #22 from thallgren)
|
206
|
+
* Use a value larger than Fixnum max to test Bignum support (pull request #18 from graaff)
|
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.
|
data/Project.yaml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
name: rgen
|
2
|
+
gemspec: rgen.gemspec
|
3
|
+
git: https://github.com/mthiede/rgen.git
|
4
|
+
version: 0.8.4
|
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.6.0', '>= 1.6.8.1'], 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}
|
data/README.rdoc
CHANGED
@@ -5,7 +5,7 @@ This means that it helps you build Metamodels, instantiate Models, modify
|
|
5
5
|
and transform Models and finally generate arbitrary textual content from it.
|
6
6
|
|
7
7
|
RGen features include:
|
8
|
-
* Supporting Ruby 1.8.
|
8
|
+
* Supporting Ruby 1.8.7, 1.9.x, 2.0, 2.1, 2.2
|
9
9
|
* Metamodel definition language (internal Ruby DSL)
|
10
10
|
* ECore Meta-metamodel with an ECore instance available for every Metamodel
|
11
11
|
* Generator creating the Ruby metamodel definition from an ECore instance
|
data/Rakefile
CHANGED
@@ -1,41 +1,38 @@
|
|
1
1
|
require 'rubygems/package_task'
|
2
2
|
require 'rdoc/task'
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'rake/testtask'
|
3
5
|
|
4
|
-
RGenGemSpec =
|
5
|
-
s.name = %q{rgen}
|
6
|
-
s.version = "0.7.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
|
6
|
+
RGenGemSpec = eval(File.read('rgen.gemspec'))
|
22
7
|
|
23
8
|
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 =
|
9
|
+
rd.main = 'README.rdoc'
|
10
|
+
rd.rdoc_files.include('README.rdoc', 'CHANGELOG', 'MIT-LICENSE', 'lib/**/*.rb')
|
11
|
+
rd.rdoc_files.exclude('lib/metamodels/*')
|
12
|
+
rd.rdoc_files.exclude('lib/ea_support/uml13*')
|
13
|
+
rd.rdoc_dir = 'doc'
|
29
14
|
end
|
30
15
|
|
31
16
|
RGenPackageTask = Gem::PackageTask.new(RGenGemSpec) do |p|
|
32
17
|
p.need_zip = false
|
33
|
-
end
|
18
|
+
end
|
19
|
+
|
20
|
+
::Rake::TestTask.new(:test) do |t|
|
21
|
+
t.test_files = ['test/rgen_test.rb']
|
22
|
+
t.warning = false
|
23
|
+
end
|
34
24
|
|
35
25
|
task :prepare_package_rdoc => :rdoc do
|
36
|
-
RGenPackageTask.package_files.include(
|
26
|
+
RGenPackageTask.package_files.include('doc/**/*')
|
37
27
|
end
|
38
28
|
|
39
29
|
task :release => [:prepare_package_rdoc, :package]
|
40
30
|
|
41
31
|
task :clobber => [:clobber_rdoc, :clobber_package]
|
32
|
+
|
33
|
+
task :ecore_to_json do
|
34
|
+
require 'rgen/ecore/ecore_to_json'
|
35
|
+
|
36
|
+
exporter = RGen::ECore::ECoreToJson.new
|
37
|
+
File.write('ecore.json', exporter.epackage_to_json_string(RGen.ecore, exporter.ecore_datatypes))
|
38
|
+
end
|
data/lib/rgen/ecore/ecore.rb
CHANGED
@@ -155,7 +155,7 @@ module RGen
|
|
155
155
|
has_many 'eAttributes', ECore::EAttribute, :derived=>true
|
156
156
|
has_many 'eReferences', ECore::EReference, :derived=>true
|
157
157
|
|
158
|
-
module ClassModule
|
158
|
+
module ClassModule
|
159
159
|
def eAllAttributes_derived
|
160
160
|
eAttributes + eSuperTypes.eAllAttributes
|
161
161
|
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,188 @@
|
|
1
|
+
require 'rgen/ecore/ecore'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module RGen
|
5
|
+
|
6
|
+
module ECore
|
7
|
+
|
8
|
+
# ECoreToJson can turn ECore models into their JSON metamodel representations
|
9
|
+
class ECoreToJson
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
def root_elements_to_json_string(root_elements)
|
16
|
+
JSON.pretty_generate(root_elements.map do |el|
|
17
|
+
if el.is_a?(RGen::ECore::EPackage)
|
18
|
+
epackage(el)
|
19
|
+
elsif el.is_a?(RGen::ECore::EClass)
|
20
|
+
eclass(el)
|
21
|
+
else
|
22
|
+
raise "Not implemented for #{el}"
|
23
|
+
end
|
24
|
+
end)
|
25
|
+
end
|
26
|
+
|
27
|
+
def epackage_to_json(package)
|
28
|
+
epackage(package)
|
29
|
+
end
|
30
|
+
|
31
|
+
def ecore_datatypes
|
32
|
+
[RGen::ECore::EString, RGen::ECore::EInt, RGen::ECore::ELong, RGen::ECore::EBoolean, RGen::ECore::EFloat,
|
33
|
+
RGen::ECore::ERubyObject, RGen::ECore::EJavaObject, RGen::ECore::ERubyClass, RGen::ECore::EJavaClass]
|
34
|
+
.map {|dt| edatatype(dt)}
|
35
|
+
end
|
36
|
+
|
37
|
+
def epackage_to_json_pretty_string(package, append = [])
|
38
|
+
JSON.pretty_generate([epackage_to_json(package)] + append)
|
39
|
+
end
|
40
|
+
|
41
|
+
def epackage_to_json_string(package, append = [])
|
42
|
+
JSON.generate([epackage_to_json(package)] + append)
|
43
|
+
end
|
44
|
+
|
45
|
+
def emodelelement(me)
|
46
|
+
{
|
47
|
+
:eAnnotations => me.eAnnotations.map { |e| eannotation(e) }
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def enamedelement(ne)
|
53
|
+
merge(emodelelement(ne), {:name => ne.name})
|
54
|
+
end
|
55
|
+
|
56
|
+
def epackage(package)
|
57
|
+
merge(enamedelement(package), {
|
58
|
+
:_class_ref => 'RGen.ECore.EPackage',
|
59
|
+
:eClassifiers => package.eClassifiers.map do |classifier|
|
60
|
+
if classifier.is_a?(RGen::ECore::EClass)
|
61
|
+
eclass(classifier)
|
62
|
+
elsif classifier.is_a?(RGen::ECore::EEnum)
|
63
|
+
eenum(classifier)
|
64
|
+
else
|
65
|
+
edatatype(classifier)
|
66
|
+
end
|
67
|
+
end,
|
68
|
+
:eSubpackages => package.eSubpackages.map { |sp| epackage(sp) },
|
69
|
+
:nsURI => package.nsURI,
|
70
|
+
:nsPrefix => package.nsPrefix
|
71
|
+
})
|
72
|
+
end
|
73
|
+
|
74
|
+
def eclassifier(classifier)
|
75
|
+
enamedelement(classifier).merge({
|
76
|
+
# omit :instanceClassName => classifier.instanceClassName
|
77
|
+
})
|
78
|
+
end
|
79
|
+
|
80
|
+
def eclass(_class)
|
81
|
+
merge(eclassifier(_class), {
|
82
|
+
:_class_ref => 'RGen.ECore.EClass',
|
83
|
+
:abstract => _class.abstract,
|
84
|
+
:interface => _class.interface,
|
85
|
+
:eStructuralFeatures => _class.eStructuralFeatures.map do |sf|
|
86
|
+
if sf.is_a?(RGen::ECore::EReference)
|
87
|
+
ereference(sf)
|
88
|
+
else
|
89
|
+
eattribute(sf)
|
90
|
+
end
|
91
|
+
end,
|
92
|
+
:eSuperTypes => _class.eSuperTypes.map { |st| {:_ref => ref_id(st)} }
|
93
|
+
})
|
94
|
+
end
|
95
|
+
|
96
|
+
def edatatype(_datatype)
|
97
|
+
merge(eclassifier(_datatype), {
|
98
|
+
:_class_ref => 'RGen.ECore.EDataType',
|
99
|
+
:serializable => _datatype.serializable,
|
100
|
+
:instanceClassName => _datatype.instanceClassName
|
101
|
+
})
|
102
|
+
end
|
103
|
+
|
104
|
+
def eenum(enum)
|
105
|
+
merge(edatatype(enum), {
|
106
|
+
:_class_ref => 'RGen.ECore.EEnum',
|
107
|
+
:eLiterals => enum.eLiterals.map do |l|
|
108
|
+
merge({}, {
|
109
|
+
:_class_ref => 'RGen.ECore.EEnumLiteral',
|
110
|
+
:value => l.value,
|
111
|
+
:literal => l.literal
|
112
|
+
})
|
113
|
+
end
|
114
|
+
})
|
115
|
+
end
|
116
|
+
|
117
|
+
def eannotation(e)
|
118
|
+
merge(emodelelement(e), {
|
119
|
+
:source => e.source,
|
120
|
+
:details => e.details.map do |d|
|
121
|
+
merge({}, {
|
122
|
+
:_class_ref => 'RGen.ECore.EStringToStringMapEntry',
|
123
|
+
:key => d.key,
|
124
|
+
:value => d.value
|
125
|
+
})
|
126
|
+
end
|
127
|
+
})
|
128
|
+
end
|
129
|
+
|
130
|
+
def etypedelement(te)
|
131
|
+
merge(enamedelement(te), {
|
132
|
+
:ordered => te.ordered,
|
133
|
+
:unique => te.unique,
|
134
|
+
:lowerBound => te.lowerBound,
|
135
|
+
:upperBound => te.upperBound,
|
136
|
+
:many => te.many,
|
137
|
+
:required => te.required,
|
138
|
+
:eType => {:_ref => te.eType ? ref_id(te.eType) : nil}
|
139
|
+
})
|
140
|
+
end
|
141
|
+
|
142
|
+
def estructuralfeature(sf)
|
143
|
+
merge(etypedelement(sf), {
|
144
|
+
:changeable => sf.changeable,
|
145
|
+
:volatile => sf.volatile,
|
146
|
+
:transient => sf.transient,
|
147
|
+
:defaultValueLiteral => sf.defaultValueLiteral,
|
148
|
+
:unsettable => sf.unsettable,
|
149
|
+
:derived => sf.derived,
|
150
|
+
})
|
151
|
+
end
|
152
|
+
|
153
|
+
def eattribute(attr)
|
154
|
+
merge(estructuralfeature(attr), {
|
155
|
+
:_class_ref => 'RGen.ECore.EAttribute',
|
156
|
+
:iD => attr.iD
|
157
|
+
})
|
158
|
+
end
|
159
|
+
|
160
|
+
def ereference(ref)
|
161
|
+
merge(estructuralfeature(ref), {
|
162
|
+
:_class_ref => 'RGen.ECore.EReference',
|
163
|
+
:containment => ref.containment,
|
164
|
+
:resolveProxies => ref.resolveProxies,
|
165
|
+
:eOpposite => ref.eOpposite ? {:_ref => "#{ref_id(ref.eOpposite.eContainer)}.#{ref.eOpposite.name}"} : nil
|
166
|
+
})
|
167
|
+
end
|
168
|
+
|
169
|
+
def ref_id(obj)
|
170
|
+
res = ref_parts(obj)
|
171
|
+
res.join('.')
|
172
|
+
end
|
173
|
+
|
174
|
+
def ref_parts(obj)
|
175
|
+
return [obj.name] unless obj&.eContainer
|
176
|
+
ref_parts(obj.eContainer) << obj.name
|
177
|
+
end
|
178
|
+
|
179
|
+
def merge(hash, values)
|
180
|
+
values.each { |k, v| hash[k] = v unless v.nil? }
|
181
|
+
hash
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
@@ -1,66 +1,131 @@
|
|
1
|
+
require 'set'
|
1
2
|
require 'rgen/ecore/ecore'
|
2
3
|
|
3
4
|
module RGen
|
4
5
|
|
5
6
|
module ECore
|
6
7
|
|
8
|
+
# ECoreToRuby can turn ECore models into their Ruby metamodel representations
|
7
9
|
class ECoreToRuby
|
8
10
|
|
9
11
|
def initialize
|
10
12
|
@modules = {}
|
11
13
|
@classifiers = {}
|
12
14
|
@features_added = {}
|
13
|
-
@
|
15
|
+
@reserved = Set.new(Object.methods)
|
14
16
|
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
18
|
+
# Create a Ruby module representing +epackage+.
|
19
|
+
# This includes all nested modules/packages, classes and enums.
|
20
|
+
#
|
21
|
+
# If a parent module is provided with the "under" parameter,
|
22
|
+
# the new module will be nested under the parent module.
|
23
|
+
#
|
24
|
+
# If the parent module has a non-temporary name,
|
25
|
+
# (more precisely: a non-temporary classpath) i.e. if it is reachable
|
26
|
+
# via a path of constant names from the root, then the nested
|
27
|
+
# modules and classes will also have non-temporary names.
|
28
|
+
# In particular, this means that they will keep their names even
|
29
|
+
# if they are assigned to new constants.
|
30
|
+
#
|
31
|
+
# If no parent module is provided or the parent module has a
|
32
|
+
# temporary name by itself, then the nested modules and classes will
|
33
|
+
# also have temporary names. This means that their name will stay
|
34
|
+
# 'volatile' until they are assigned to constants reachable from
|
35
|
+
# the root and the Module#name method is called for the first time.
|
36
|
+
#
|
37
|
+
# While the second approach is more flexible, it can come with a major
|
38
|
+
# performance impact. The reason is that Ruby searches the space of
|
39
|
+
# all known non-temporary classes/modules every time the name
|
40
|
+
# of a class/module with a temporary name is queried.
|
41
|
+
#
|
42
|
+
def create_module(epackage, under=Module.new)
|
43
|
+
with_empty_constant_order_helper do
|
44
|
+
temp = under.to_s.start_with?("#")
|
45
|
+
mod = create_module_internal(epackage, under, temp)
|
31
46
|
|
32
|
-
# create classes only after all modules have been created
|
33
|
-
# otherwise classes may be created multiple times
|
34
|
-
if top
|
35
47
|
epackage.eAllClassifiers.each do |c|
|
36
48
|
if c.is_a?(RGen::ECore::EClass)
|
37
|
-
create_class(c)
|
49
|
+
create_class(c, temp)
|
38
50
|
elsif c.is_a?(RGen::ECore::EEnum)
|
39
51
|
create_enum(c)
|
40
52
|
end
|
41
53
|
end
|
42
|
-
|
54
|
+
|
55
|
+
load_classes_with_reserved_keywords(epackage)
|
56
|
+
mod
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
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
|
43
69
|
end
|
44
|
-
m
|
45
70
|
end
|
46
71
|
|
47
|
-
def
|
72
|
+
def create_module_internal(epackage, under, temp)
|
73
|
+
return @modules[epackage] if @modules[epackage]
|
74
|
+
|
75
|
+
if temp
|
76
|
+
mod = Module.new do
|
77
|
+
extend RGen::MetamodelBuilder::ModuleExtension
|
78
|
+
end
|
79
|
+
under.const_set(epackage.name, mod)
|
80
|
+
else
|
81
|
+
under.module_eval <<-END
|
82
|
+
module #{epackage.name}
|
83
|
+
extend RGen::MetamodelBuilder::ModuleExtension
|
84
|
+
end
|
85
|
+
END
|
86
|
+
mod = under.const_get(epackage.name)
|
87
|
+
end
|
88
|
+
@modules[epackage] = mod
|
89
|
+
|
90
|
+
epackage.eSubpackages.each{|p| create_module_internal(p, mod, temp)}
|
91
|
+
mod._set_ecore_internal(epackage)
|
92
|
+
|
93
|
+
mod
|
94
|
+
end
|
95
|
+
|
96
|
+
def create_class(eclass, temp)
|
48
97
|
return @classifiers[eclass] if @classifiers[eclass]
|
49
98
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
99
|
+
mod = @modules[eclass.ePackage]
|
100
|
+
if temp
|
101
|
+
cls = Class.new(super_class(eclass, temp)) do
|
102
|
+
abstract if eclass.abstract
|
103
|
+
class << self
|
104
|
+
attr_accessor :_ecore_to_ruby
|
105
|
+
end
|
54
106
|
end
|
107
|
+
mod.const_set(eclass.name, cls)
|
108
|
+
else
|
109
|
+
mod.module_eval <<-END
|
110
|
+
class #{eclass.name} < #{super_class(eclass, temp)}
|
111
|
+
#{eclass.abstract ? 'abstract' : ''}
|
112
|
+
class << self
|
113
|
+
attr_accessor :_ecore_to_ruby
|
114
|
+
end
|
115
|
+
end
|
116
|
+
END
|
117
|
+
cls = mod.const_get(eclass.name)
|
55
118
|
end
|
119
|
+
|
56
120
|
class << eclass
|
57
121
|
attr_accessor :instanceClass
|
58
122
|
def instanceClassName
|
59
123
|
instanceClass.to_s
|
60
124
|
end
|
61
125
|
end
|
62
|
-
eclass.instanceClass =
|
63
|
-
|
126
|
+
eclass.instanceClass = cls
|
127
|
+
|
128
|
+
cls::ClassModule.module_eval do
|
64
129
|
alias _method_missing method_missing
|
65
130
|
def method_missing(m, *args)
|
66
131
|
if self.class._ecore_to_ruby.add_features(self.class.ecore)
|
@@ -75,12 +140,11 @@ class ECoreToRuby
|
|
75
140
|
_respond_to(m)
|
76
141
|
end
|
77
142
|
end
|
78
|
-
@classifiers[eclass] =
|
79
|
-
|
80
|
-
|
143
|
+
@classifiers[eclass] = cls
|
144
|
+
cls._set_ecore_internal(eclass)
|
145
|
+
cls._ecore_to_ruby = self
|
81
146
|
|
82
|
-
|
83
|
-
c
|
147
|
+
cls
|
84
148
|
end
|
85
149
|
|
86
150
|
def create_enum(eenum)
|
@@ -89,7 +153,7 @@ class ECoreToRuby
|
|
89
153
|
e = RGen::MetamodelBuilder::DataTypes::Enum.new(eenum.eLiterals.collect{|l| l.name.to_sym})
|
90
154
|
@classifiers[eenum] = e
|
91
155
|
|
92
|
-
|
156
|
+
@modules[eenum.ePackage].const_set(eenum.name, e)
|
93
157
|
e
|
94
158
|
end
|
95
159
|
|
@@ -126,6 +190,53 @@ class ECoreToRuby
|
|
126
190
|
end
|
127
191
|
end
|
128
192
|
|
193
|
+
def super_class(eclass, temp)
|
194
|
+
super_types = eclass.eSuperTypes
|
195
|
+
if temp
|
196
|
+
case super_types.size
|
197
|
+
when 0
|
198
|
+
RGen::MetamodelBuilder::MMBase
|
199
|
+
when 1
|
200
|
+
create_class(super_types.first, temp)
|
201
|
+
else
|
202
|
+
RGen::MetamodelBuilder::MMMultiple(*super_types.collect{|t| create_class(t, temp)})
|
203
|
+
end
|
204
|
+
else
|
205
|
+
case super_types.size
|
206
|
+
when 0
|
207
|
+
"RGen::MetamodelBuilder::MMBase"
|
208
|
+
when 1
|
209
|
+
create_class(super_types.first, temp).name
|
210
|
+
else
|
211
|
+
"RGen::MetamodelBuilder::MMMultiple(" +
|
212
|
+
super_types.collect{|t| create_class(t, temp).name}.join(",") + ")"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
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
|
+
|
238
|
+
public
|
239
|
+
|
129
240
|
def add_features(eclass)
|
130
241
|
return false if @features_added[eclass]
|
131
242
|
c = @classifiers[eclass]
|
@@ -147,18 +258,6 @@ class ECoreToRuby
|
|
147
258
|
true
|
148
259
|
end
|
149
260
|
|
150
|
-
def super_class(eclass)
|
151
|
-
super_types = eclass.eSuperTypes
|
152
|
-
case super_types.size
|
153
|
-
when 0
|
154
|
-
RGen::MetamodelBuilder::MMBase
|
155
|
-
when 1
|
156
|
-
create_class(super_types.first)
|
157
|
-
else
|
158
|
-
RGen::MetamodelBuilder::MMMultiple(*super_types.collect{|t| create_class(t)})
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
261
|
end
|
163
262
|
|
164
263
|
end
|
@@ -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
|