rgen 0.7.0 → 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +23 -0
- data/README.rdoc +1 -1
- data/Rakefile +15 -25
- data/lib/rgen/ecore/ecore.rb +1 -1
- data/lib/rgen/ecore/ecore_ext.rb +9 -1
- data/lib/rgen/ecore/ecore_to_ruby.rb +133 -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 +32 -8
- 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 +71 -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 +61 -20
- 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: d1c27a6cc15f063ebc9483cb56253ebd20721cd2
|
4
|
+
data.tar.gz: b30dfcf5b91d19a8d26b0cc66a5dec9d3c0471c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b74eb0928f9e39911b25dddbff8c73b12a331d651d59fdb27672794c6f6477bcdf23b3e8ac17ca97c2b3138dc33a3788a48ae6100493a710ff06e5557093dc8
|
7
|
+
data.tar.gz: cfe2866c2692b7a408cd460205cdc105f2cf792262104adfb6a0f0aa55bf917c26193766abebf43ccfd2f218f74e78910f20b82fa17d585beaca5345301bf985
|
data/CHANGELOG
CHANGED
@@ -195,3 +195,26 @@
|
|
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
|
+
|
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,39 +1,29 @@
|
|
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]
|
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
|
@@ -4,63 +4,115 @@ module RGen
|
|
4
4
|
|
5
5
|
module ECore
|
6
6
|
|
7
|
+
# ECoreToRuby can turn ECore models into their Ruby metamodel representations
|
7
8
|
class ECoreToRuby
|
8
9
|
|
9
10
|
def initialize
|
10
11
|
@modules = {}
|
11
12
|
@classifiers = {}
|
12
13
|
@features_added = {}
|
13
|
-
@in_create_module = false
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
16
|
+
# Create a Ruby module representing +epackage+.
|
17
|
+
# This includes all nested modules/packages, classes and enums.
|
18
|
+
#
|
19
|
+
# If a parent module is provided with the "under" parameter,
|
20
|
+
# the new module will be nested under the parent module.
|
21
|
+
#
|
22
|
+
# If the parent module has a non-temporary name,
|
23
|
+
# (more precisely: a non-temporary classpath) i.e. if it is reachable
|
24
|
+
# via a path of constant names from the root, then the nested
|
25
|
+
# modules and classes will also have non-temporary names.
|
26
|
+
# In particular, this means that they will keep their names even
|
27
|
+
# if they are assigned to new constants.
|
28
|
+
#
|
29
|
+
# If no parent module is provided or the parent module has a
|
30
|
+
# temporary name by itself, then the nested modules and classes will
|
31
|
+
# also have temporary names. This means that their name will stay
|
32
|
+
# 'volatile' until they are assigned to constants reachable from
|
33
|
+
# the root and the Module#name method is called for the first time.
|
34
|
+
#
|
35
|
+
# While the second approach is more flexible, it can come with a major
|
36
|
+
# performance impact. The reason is that Ruby searches the space of
|
37
|
+
# all known non-temporary classes/modules every time the name
|
38
|
+
# of a class/module with a temporary name is queried.
|
39
|
+
#
|
40
|
+
def create_module(epackage, under=Module.new)
|
41
|
+
with_empty_constant_order_helper do
|
42
|
+
temp = under.to_s.start_with?("#")
|
43
|
+
mod = create_module_internal(epackage, under, temp)
|
31
44
|
|
32
|
-
# create classes only after all modules have been created
|
33
|
-
# otherwise classes may be created multiple times
|
34
|
-
if top
|
35
45
|
epackage.eAllClassifiers.each do |c|
|
36
46
|
if c.is_a?(RGen::ECore::EClass)
|
37
|
-
create_class(c)
|
47
|
+
create_class(c, temp)
|
38
48
|
elsif c.is_a?(RGen::ECore::EEnum)
|
39
49
|
create_enum(c)
|
40
50
|
end
|
41
51
|
end
|
42
|
-
|
52
|
+
|
53
|
+
mod
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def create_module_internal(epackage, under, temp)
|
60
|
+
return @modules[epackage] if @modules[epackage]
|
61
|
+
|
62
|
+
if temp
|
63
|
+
mod = Module.new do
|
64
|
+
extend RGen::MetamodelBuilder::ModuleExtension
|
65
|
+
end
|
66
|
+
under.const_set(epackage.name, mod)
|
67
|
+
else
|
68
|
+
under.module_eval <<-END
|
69
|
+
module #{epackage.name}
|
70
|
+
extend RGen::MetamodelBuilder::ModuleExtension
|
71
|
+
end
|
72
|
+
END
|
73
|
+
mod = under.const_get(epackage.name)
|
43
74
|
end
|
44
|
-
|
75
|
+
@modules[epackage] = mod
|
76
|
+
|
77
|
+
epackage.eSubpackages.each{|p| create_module_internal(p, mod, temp)}
|
78
|
+
mod._set_ecore_internal(epackage)
|
79
|
+
|
80
|
+
mod
|
45
81
|
end
|
46
82
|
|
47
|
-
def create_class(eclass)
|
83
|
+
def create_class(eclass, temp)
|
48
84
|
return @classifiers[eclass] if @classifiers[eclass]
|
49
85
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
86
|
+
mod = @modules[eclass.ePackage]
|
87
|
+
if temp
|
88
|
+
cls = Class.new(super_class(eclass, temp)) do
|
89
|
+
abstract if eclass.abstract
|
90
|
+
class << self
|
91
|
+
attr_accessor :_ecore_to_ruby
|
92
|
+
end
|
54
93
|
end
|
94
|
+
mod.const_set(eclass.name, cls)
|
95
|
+
else
|
96
|
+
mod.module_eval <<-END
|
97
|
+
class #{eclass.name} < #{super_class(eclass, temp)}
|
98
|
+
#{eclass.abstract ? 'abstract' : ''}
|
99
|
+
class << self
|
100
|
+
attr_accessor :_ecore_to_ruby
|
101
|
+
end
|
102
|
+
end
|
103
|
+
END
|
104
|
+
cls = mod.const_get(eclass.name)
|
55
105
|
end
|
106
|
+
|
56
107
|
class << eclass
|
57
108
|
attr_accessor :instanceClass
|
58
109
|
def instanceClassName
|
59
110
|
instanceClass.to_s
|
60
111
|
end
|
61
112
|
end
|
62
|
-
eclass.instanceClass =
|
63
|
-
|
113
|
+
eclass.instanceClass = cls
|
114
|
+
|
115
|
+
cls::ClassModule.module_eval do
|
64
116
|
alias _method_missing method_missing
|
65
117
|
def method_missing(m, *args)
|
66
118
|
if self.class._ecore_to_ruby.add_features(self.class.ecore)
|
@@ -75,12 +127,11 @@ class ECoreToRuby
|
|
75
127
|
_respond_to(m)
|
76
128
|
end
|
77
129
|
end
|
78
|
-
@classifiers[eclass] =
|
79
|
-
|
80
|
-
|
130
|
+
@classifiers[eclass] = cls
|
131
|
+
cls._set_ecore_internal(eclass)
|
132
|
+
cls._ecore_to_ruby = self
|
81
133
|
|
82
|
-
|
83
|
-
c
|
134
|
+
cls
|
84
135
|
end
|
85
136
|
|
86
137
|
def create_enum(eenum)
|
@@ -89,7 +140,7 @@ class ECoreToRuby
|
|
89
140
|
e = RGen::MetamodelBuilder::DataTypes::Enum.new(eenum.eLiterals.collect{|l| l.name.to_sym})
|
90
141
|
@classifiers[eenum] = e
|
91
142
|
|
92
|
-
|
143
|
+
@modules[eenum.ePackage].const_set(eenum.name, e)
|
93
144
|
e
|
94
145
|
end
|
95
146
|
|
@@ -126,6 +177,53 @@ class ECoreToRuby
|
|
126
177
|
end
|
127
178
|
end
|
128
179
|
|
180
|
+
def super_class(eclass, temp)
|
181
|
+
super_types = eclass.eSuperTypes
|
182
|
+
if temp
|
183
|
+
case super_types.size
|
184
|
+
when 0
|
185
|
+
RGen::MetamodelBuilder::MMBase
|
186
|
+
when 1
|
187
|
+
create_class(super_types.first, temp)
|
188
|
+
else
|
189
|
+
RGen::MetamodelBuilder::MMMultiple(*super_types.collect{|t| create_class(t, temp)})
|
190
|
+
end
|
191
|
+
else
|
192
|
+
case super_types.size
|
193
|
+
when 0
|
194
|
+
"RGen::MetamodelBuilder::MMBase"
|
195
|
+
when 1
|
196
|
+
create_class(super_types.first, temp).name
|
197
|
+
else
|
198
|
+
"RGen::MetamodelBuilder::MMMultiple(" +
|
199
|
+
super_types.collect{|t| create_class(t, temp).name}.join(",") + ")"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
class EmptyConstantOrderHelper
|
205
|
+
def classCreated(c); end
|
206
|
+
def moduleCreated(m); end
|
207
|
+
def enumCreated(e); end
|
208
|
+
end
|
209
|
+
|
210
|
+
def with_empty_constant_order_helper
|
211
|
+
orig_coh = RGen::MetamodelBuilder::ConstantOrderHelper
|
212
|
+
RGen::MetamodelBuilder.instance_eval { remove_const(:ConstantOrderHelper) }
|
213
|
+
RGen::MetamodelBuilder.const_set(:ConstantOrderHelper, EmptyConstantOrderHelper.new)
|
214
|
+
|
215
|
+
begin
|
216
|
+
result = yield
|
217
|
+
ensure
|
218
|
+
RGen::MetamodelBuilder.instance_eval { remove_const(:ConstantOrderHelper) }
|
219
|
+
RGen::MetamodelBuilder.const_set(:ConstantOrderHelper, orig_coh)
|
220
|
+
end
|
221
|
+
|
222
|
+
result
|
223
|
+
end
|
224
|
+
|
225
|
+
public
|
226
|
+
|
129
227
|
def add_features(eclass)
|
130
228
|
return false if @features_added[eclass]
|
131
229
|
c = @classifiers[eclass]
|
@@ -147,18 +245,6 @@ class ECoreToRuby
|
|
147
245
|
true
|
148
246
|
end
|
149
247
|
|
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
248
|
end
|
163
249
|
|
164
250
|
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
|
@@ -8,107 +8,112 @@ module Instantiator
|
|
8
8
|
# Derive your own instantiator from this class or use it as is.
|
9
9
|
#
|
10
10
|
class DefaultXMLInstantiator < NodebasedXMLInstantiator
|
11
|
-
|
11
|
+
include Util::NameHelper
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
13
|
+
NamespaceDescriptor = Struct.new(:prefix, :target)
|
14
|
+
|
15
|
+
class << self
|
16
|
+
|
17
|
+
def map_tag_ns(from, to, prefix="")
|
18
|
+
tag_ns_map[from] = NamespaceDescriptor.new(prefix, to)
|
19
|
+
end
|
20
|
+
|
21
|
+
def tag_ns_map # :nodoc:
|
22
|
+
@tag_ns_map ||={}
|
23
|
+
@tag_ns_map
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(env, default_module, create_mm=false)
|
29
|
+
super(env)
|
30
|
+
@default_module = default_module
|
31
|
+
@create_mm = create_mm
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_descent(node)
|
35
|
+
obj = new_object(node)
|
36
|
+
@env << obj unless obj.nil?
|
37
|
+
node.object = obj
|
38
|
+
node.attributes.each_pair { |k,v| set_attribute(node, k, v) }
|
39
|
+
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
41
|
+
def on_ascent(node)
|
42
|
+
node.children.each { |c| assoc_p2c(node, c) }
|
43
|
+
node.object.class.has_attr 'chardata', Object unless node.object.respond_to?(:chardata)
|
44
|
+
set_attribute(node, "chardata", node.chardata)
|
45
|
+
end
|
46
|
+
|
47
47
|
def class_name(str)
|
48
48
|
saneClassName(str)
|
49
49
|
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
51
|
+
def new_object(node)
|
52
|
+
ns_desc = self.class.tag_ns_map[node.namespace]
|
53
|
+
class_name = class_name(ns_desc.nil? ? node.qtag : ns_desc.prefix+node.tag)
|
54
|
+
mod = (ns_desc && ns_desc.target) || @default_module
|
55
|
+
build_on_error(NameError, :build_class, class_name, mod) do
|
56
|
+
begin
|
57
|
+
mod.const_get(class_name, false).new
|
58
|
+
rescue ArgumentError
|
59
|
+
# Ruby 1.8
|
60
|
+
mod.const_get(class_name).new
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
59
64
|
|
60
|
-
|
61
|
-
|
62
|
-
|
65
|
+
def build_class(name, mod)
|
66
|
+
mod.const_set(name, Class.new(RGen::MetamodelBuilder::MMBase))
|
67
|
+
end
|
63
68
|
|
64
69
|
def method_name(str)
|
65
70
|
saneMethodName(str)
|
66
71
|
end
|
67
72
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
73
|
+
def assoc_p2c(parent, child)
|
74
|
+
return unless parent.object && child.object
|
75
|
+
method_name = method_name(className(child.object))
|
76
|
+
build_on_error(NoMethodError, :build_p2c_assoc, parent, child, method_name) do
|
77
|
+
parent.object.addGeneric(method_name, child.object)
|
78
|
+
child.object.setGeneric("parent", parent.object)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def build_p2c_assoc(parent, child, method_name)
|
83
|
+
parent.object.class.has_many(method_name, child.object.class)
|
84
|
+
child.object.class.has_one("parent", RGen::MetamodelBuilder::MMBase)
|
85
|
+
end
|
86
|
+
|
87
|
+
def set_attribute(node, attr, value)
|
88
|
+
return unless node.object
|
89
|
+
build_on_error(NoMethodError, :build_attribute, node, attr, value) do
|
90
|
+
node.object.setGeneric(method_name(attr), value)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def build_attribute(node, attr, value)
|
95
|
+
node.object.class.has_attr(method_name(attr))
|
96
|
+
end
|
92
97
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
98
|
+
protected
|
99
|
+
|
100
|
+
# Helper method for implementing classes.
|
101
|
+
# This method yields the given block.
|
102
|
+
# If the metamodel should be create automatically (see constructor)
|
103
|
+
# rescues +error+ and calls +builder_method+ with +args+, then
|
104
|
+
# yields the block again.
|
105
|
+
def build_on_error(error, builder_method, *args)
|
106
|
+
begin
|
107
|
+
yield
|
108
|
+
rescue error
|
109
|
+
if @create_mm
|
110
|
+
send(builder_method, *args)
|
111
|
+
yield
|
112
|
+
else
|
113
|
+
raise
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
112
117
|
|
113
118
|
end
|
114
119
|
|