rgen 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +28 -0
- data/Rakefile +3 -4
- data/lib/ea_support/uml13_ea_metamodel.rb +3 -3
- data/lib/ea_support/uml13_ea_to_uml13.rb +33 -2
- data/lib/ea_support/uml13_to_uml13_ea.rb +7 -0
- data/lib/mmgen/mm_ext/ecore_mmgen_ext.rb +4 -4
- data/lib/mmgen/templates/metamodel_generator.tpl +143 -143
- data/lib/rgen/ecore/ecore.rb +11 -1
- data/lib/rgen/ecore/ecore_interface.rb +47 -0
- data/lib/rgen/ecore/ecore_to_ruby.rb +166 -0
- data/lib/rgen/ecore/{ecore_transformer.rb → ruby_to_ecore.rb} +11 -11
- data/lib/rgen/environment.rb +15 -2
- data/lib/rgen/fragment/dump_file_cache.rb +63 -0
- data/lib/rgen/fragment/fragmented_model.rb +139 -0
- data/lib/rgen/fragment/model_fragment.rb +268 -0
- data/lib/rgen/instantiator/abstract_xml_instantiator.rb +44 -72
- data/lib/rgen/instantiator/default_xml_instantiator.rb +2 -2
- data/lib/rgen/instantiator/ecore_xml_instantiator.rb +16 -1
- data/lib/rgen/instantiator/json_instantiator.rb +16 -2
- data/lib/rgen/instantiator/nodebased_xml_instantiator.rb +118 -138
- data/lib/rgen/instantiator/qualified_name_resolver.rb +5 -1
- data/lib/rgen/instantiator/reference_resolver.rb +126 -24
- data/lib/rgen/instantiator/xmi11_instantiator.rb +6 -2
- data/lib/rgen/metamodel_builder.rb +18 -6
- data/lib/rgen/metamodel_builder/builder_extensions.rb +431 -407
- data/lib/rgen/metamodel_builder/builder_runtime.rb +8 -8
- data/lib/rgen/metamodel_builder/constant_order_helper.rb +4 -4
- data/lib/rgen/metamodel_builder/data_types.rb +5 -1
- data/lib/rgen/metamodel_builder/intermediate/feature.rb +167 -0
- data/lib/rgen/metamodel_builder/module_extension.rb +2 -2
- data/lib/rgen/model_builder.rb +10 -5
- data/lib/rgen/model_builder/builder_context.rb +17 -1
- data/lib/rgen/serializer/opposite_reference_filter.rb +18 -0
- data/lib/rgen/serializer/qualified_name_provider.rb +45 -0
- data/lib/rgen/template_language/template_container.rb +3 -1
- data/lib/rgen/{auto_class_creator.rb → util/auto_class_creator.rb} +6 -1
- data/lib/rgen/util/cached_glob.rb +67 -0
- data/lib/rgen/util/file_cache_map.rb +104 -0
- data/lib/rgen/util/file_change_detector.rb +78 -0
- data/lib/rgen/{method_delegation.rb → util/method_delegation.rb} +18 -3
- data/lib/rgen/{model_comparator.rb → util/model_comparator.rb} +17 -5
- data/lib/rgen/{model_comparator_base.rb → util/model_comparator_base.rb} +6 -1
- data/lib/rgen/{model_dumper.rb → util/model_dumper.rb} +6 -1
- data/lib/rgen/{name_helper.rb → util/name_helper.rb} +6 -1
- data/lib/rgen/util/pattern_matcher.rb +329 -0
- data/lib/transformers/uml13_to_ecore.rb +103 -60
- data/test/ecore_self_test.rb +43 -42
- data/test/json_test.rb +15 -0
- data/test/metamodel_builder_test.rb +361 -206
- data/test/metamodel_from_ecore_test.rb +45 -0
- data/test/metamodel_order_test.rb +10 -4
- data/test/metamodel_roundtrip_test.rb +2 -2
- data/test/metamodel_roundtrip_test/TestModel_Regenerated.rb +1 -1
- data/test/metamodel_roundtrip_test/houseMetamodel_Regenerated.ecore +50 -50
- data/test/method_delegation_test.rb +9 -9
- data/test/model_builder/ecore_internal.rb +19 -9
- data/test/model_builder/serializer_test.rb +1 -1
- data/test/reference_resolver_test.rb +79 -12
- data/test/rgen_test.rb +2 -0
- data/test/template_language_test.rb +7 -0
- data/test/template_language_test/templates/callback_indent_test/a.tpl +12 -0
- data/test/template_language_test/templates/callback_indent_test/b.tpl +5 -0
- data/test/testmodel/ea_testmodel_regenerated.xml +588 -583
- data/test/transformer_test.rb +3 -3
- data/test/util/file_cache_map_test.rb +91 -0
- data/test/util/file_cache_map_test/testdir/fileA +1 -0
- data/test/util_test.rb +4 -0
- data/test/xml_instantiator_test.rb +139 -135
- metadata +49 -104
- data/lib/rgen/ecore/ecore_instantiator.rb +0 -31
- data/lib/rgen/metamodel_builder/metamodel_description.rb +0 -232
- data/redist/xmlscan/ChangeLog +0 -1301
- data/redist/xmlscan/README +0 -34
- data/redist/xmlscan/THANKS +0 -11
- data/redist/xmlscan/doc/changes.html +0 -74
- data/redist/xmlscan/doc/changes.rd +0 -80
- data/redist/xmlscan/doc/en/conformance.html +0 -136
- data/redist/xmlscan/doc/en/conformance.rd +0 -152
- data/redist/xmlscan/doc/en/manual.html +0 -356
- data/redist/xmlscan/doc/en/manual.rd +0 -402
- data/redist/xmlscan/doc/ja/conformance.ja.html +0 -118
- data/redist/xmlscan/doc/ja/conformance.ja.rd +0 -134
- data/redist/xmlscan/doc/ja/manual.ja.html +0 -325
- data/redist/xmlscan/doc/ja/manual.ja.rd +0 -370
- data/redist/xmlscan/doc/src/Makefile +0 -41
- data/redist/xmlscan/doc/src/conformance.rd.src +0 -256
- data/redist/xmlscan/doc/src/langsplit.rb +0 -110
- data/redist/xmlscan/doc/src/manual.rd.src +0 -614
- data/redist/xmlscan/install.rb +0 -41
- data/redist/xmlscan/lib/xmlscan/encoding.rb +0 -311
- data/redist/xmlscan/lib/xmlscan/htmlscan.rb +0 -289
- data/redist/xmlscan/lib/xmlscan/namespace.rb +0 -352
- data/redist/xmlscan/lib/xmlscan/parser.rb +0 -299
- data/redist/xmlscan/lib/xmlscan/scanner.rb +0 -1109
- data/redist/xmlscan/lib/xmlscan/version.rb +0 -22
- data/redist/xmlscan/lib/xmlscan/visitor.rb +0 -158
- data/redist/xmlscan/lib/xmlscan/xmlchar.rb +0 -441
- data/redist/xmlscan/memo/CONFORMANCE +0 -1249
- data/redist/xmlscan/memo/PRODUCTIONS +0 -195
- data/redist/xmlscan/memo/contentspec.ry +0 -335
- data/redist/xmlscan/samples/chibixml.rb +0 -105
- data/redist/xmlscan/samples/getxmlchar.rb +0 -122
- data/redist/xmlscan/samples/rexml.rb +0 -159
- data/redist/xmlscan/samples/xmlbench.rb +0 -88
- data/redist/xmlscan/samples/xmlbench/parser/chibixml.rb +0 -22
- data/redist/xmlscan/samples/xmlbench/parser/nqxml.rb +0 -29
- data/redist/xmlscan/samples/xmlbench/parser/rexml.rb +0 -62
- data/redist/xmlscan/samples/xmlbench/parser/xmlparser.rb +0 -22
- data/redist/xmlscan/samples/xmlbench/parser/xmlscan-0.0.10.rb +0 -62
- data/redist/xmlscan/samples/xmlbench/parser/xmlscan-chibixml.rb +0 -22
- data/redist/xmlscan/samples/xmlbench/parser/xmlscan-rexml.rb +0 -22
- data/redist/xmlscan/samples/xmlbench/parser/xmlscan.rb +0 -99
- data/redist/xmlscan/samples/xmlbench/xmlbench-lib.rb +0 -116
- data/redist/xmlscan/samples/xmlconftest.rb +0 -200
- data/redist/xmlscan/test.rb +0 -7
- data/redist/xmlscan/tests/deftestcase.rb +0 -73
- data/redist/xmlscan/tests/runtest.rb +0 -47
- data/redist/xmlscan/tests/testall.rb +0 -14
- data/redist/xmlscan/tests/testencoding.rb +0 -438
- data/redist/xmlscan/tests/testhtmlscan.rb +0 -752
- data/redist/xmlscan/tests/testnamespace.rb +0 -457
- data/redist/xmlscan/tests/testparser.rb +0 -591
- data/redist/xmlscan/tests/testscanner.rb +0 -1749
- data/redist/xmlscan/tests/testxmlchar.rb +0 -143
- data/redist/xmlscan/tests/visitor.rb +0 -34
|
@@ -36,7 +36,11 @@ class XMI11Instantiator < AbstractXMLInstantiator
|
|
|
36
36
|
newval = @element_by_id[rd.value]
|
|
37
37
|
end
|
|
38
38
|
log WARN, "Could not resolve reference #{rd.attribute} on #{rd.object}" unless newval
|
|
39
|
-
|
|
39
|
+
begin
|
|
40
|
+
rd.object.setGeneric(rd.attribute,newval)
|
|
41
|
+
rescue Exception
|
|
42
|
+
log WARN, "Could not set reference #{rd.attribute} on #{rd.object}"
|
|
43
|
+
end
|
|
40
44
|
end
|
|
41
45
|
end
|
|
42
46
|
|
|
@@ -161,4 +165,4 @@ class XMI11Instantiator < AbstractXMLInstantiator
|
|
|
161
165
|
@eAllStructuralFeatures[element.class] ||= element.class.ecore.eAllStructuralFeatures
|
|
162
166
|
end
|
|
163
167
|
|
|
164
|
-
end
|
|
168
|
+
end
|
|
@@ -7,7 +7,7 @@ require 'rgen/metamodel_builder/builder_extensions'
|
|
|
7
7
|
require 'rgen/metamodel_builder/module_extension'
|
|
8
8
|
require 'rgen/metamodel_builder/data_types'
|
|
9
9
|
require 'rgen/metamodel_builder/mm_multiple'
|
|
10
|
-
require 'rgen/ecore/
|
|
10
|
+
require 'rgen/ecore/ecore_interface'
|
|
11
11
|
|
|
12
12
|
module RGen
|
|
13
13
|
|
|
@@ -182,25 +182,37 @@ module MetamodelBuilder
|
|
|
182
182
|
include DataTypes
|
|
183
183
|
extend BuilderExtensions
|
|
184
184
|
extend ModuleExtension
|
|
185
|
-
extend RGen::ECore::
|
|
185
|
+
extend RGen::ECore::ECoreInterface
|
|
186
186
|
|
|
187
187
|
def initialize(arg=nil)
|
|
188
|
+
raise StandardError.new("Class #{self.class} is abstract") if self.class._abstract_class
|
|
188
189
|
arg.each_pair { |k,v| setGeneric(k, v) } if arg.is_a?(Hash)
|
|
189
190
|
end
|
|
191
|
+
|
|
192
|
+
# Object#inspect causes problems on most models
|
|
193
|
+
def inspect
|
|
194
|
+
self.class.name
|
|
195
|
+
end
|
|
190
196
|
|
|
191
197
|
def self.method_added(m)
|
|
192
198
|
raise "Do not add methods to model classes directly, add them to the ClassModule instead"
|
|
193
199
|
end
|
|
194
200
|
end
|
|
195
201
|
|
|
196
|
-
# Instances of
|
|
197
|
-
|
|
198
|
-
|
|
202
|
+
# Instances of MMGeneric can be used as values of any attribute are reference
|
|
203
|
+
class MMGeneric
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# MMProxy objects can be used instead of real target elements in case references should be resolved later on
|
|
207
|
+
class MMProxy < MMGeneric
|
|
199
208
|
# The +targetIdentifer+ is an object identifying the element the proxy represents
|
|
200
209
|
attr_accessor :targetIdentifier
|
|
210
|
+
# +data+ is optional additional information to be associated with the proxy
|
|
211
|
+
attr_accessor :data
|
|
201
212
|
|
|
202
|
-
def initialize(ident=nil)
|
|
213
|
+
def initialize(ident=nil, data=nil)
|
|
203
214
|
@targetIdentifier = ident
|
|
215
|
+
@data = data
|
|
204
216
|
end
|
|
205
217
|
end
|
|
206
218
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# (c) Martin Thiede, 2006
|
|
3
3
|
|
|
4
4
|
require 'erb'
|
|
5
|
-
require 'rgen/metamodel_builder/
|
|
5
|
+
require 'rgen/metamodel_builder/intermediate/feature'
|
|
6
6
|
|
|
7
7
|
module RGen
|
|
8
8
|
|
|
@@ -16,240 +16,240 @@ module MetamodelBuilder
|
|
|
16
16
|
# See MetamodelBuilder for an example.
|
|
17
17
|
#
|
|
18
18
|
module BuilderExtensions
|
|
19
|
-
|
|
19
|
+
include Util::NameHelper
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
end
|
|
30
|
-
def annotation(hash)
|
|
31
|
-
@props1.annotations << Intermediate::Annotation.new(hash)
|
|
32
|
-
end
|
|
33
|
-
def opposite_annotation(hash)
|
|
34
|
-
raise "No opposite available" unless @props2
|
|
35
|
-
@props2.annotations << Intermediate::Annotation.new(hash)
|
|
36
|
-
end
|
|
21
|
+
class FeatureBlockEvaluator
|
|
22
|
+
def self.eval(block, props1, props2=nil)
|
|
23
|
+
return unless block
|
|
24
|
+
e = self.new(props1, props2)
|
|
25
|
+
e.instance_eval(&block)
|
|
26
|
+
end
|
|
27
|
+
def initialize(props1, props2)
|
|
28
|
+
@props1, @props2 = props1, props2
|
|
37
29
|
end
|
|
30
|
+
def annotation(hash)
|
|
31
|
+
@props1.annotations << Intermediate::Annotation.new(hash)
|
|
32
|
+
end
|
|
33
|
+
def opposite_annotation(hash)
|
|
34
|
+
raise "No opposite available" unless @props2
|
|
35
|
+
@props2.annotations << Intermediate::Annotation.new(hash)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
39
|
+
# Add an attribute which can hold a single value.
|
|
40
|
+
# 'role' specifies the name which is used to access the attribute.
|
|
41
|
+
# 'target_class' specifies the type of objects which can be held by this attribute.
|
|
42
|
+
# If no target class is given, String will be default.
|
|
43
|
+
#
|
|
44
|
+
# This class method adds the following instance methods, where 'role' is to be
|
|
45
|
+
# replaced by the given role name:
|
|
46
|
+
# class#role # getter
|
|
47
|
+
# class#role=(value) # setter
|
|
48
|
+
def has_attr(role, target_class=nil, raw_props={}, &block)
|
|
49
|
+
props = Intermediate::Attribute.new(target_class, _ownProps(raw_props).merge({
|
|
50
|
+
:name=>role, :upperBound=>1}))
|
|
51
|
+
raise "No opposite available" unless _oppositeProps(raw_props).empty?
|
|
52
|
+
FeatureBlockEvaluator.eval(block, props)
|
|
53
|
+
_build_internal(props)
|
|
54
|
+
end
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
56
|
+
# Add an attribute which can hold multiple values.
|
|
57
|
+
# 'role' specifies the name which is used to access the attribute.
|
|
58
|
+
# 'target_class' specifies the type of objects which can be held by this attribute.
|
|
59
|
+
# If no target class is given, String will be default.
|
|
60
|
+
#
|
|
61
|
+
# This class method adds the following instance methods, where 'role' is to be
|
|
62
|
+
# replaced by the given role name:
|
|
63
|
+
# class#addRole(value, index=-1)
|
|
64
|
+
# class#removeRole(value)
|
|
65
|
+
# class#role # getter, returns an array
|
|
66
|
+
# class#role= # setter, sets multiple values at once
|
|
67
|
+
# Note that the first letter of the role name is turned into an uppercase
|
|
68
|
+
# for the add and remove methods.
|
|
69
|
+
def has_many_attr(role, target_class=nil, raw_props={}, &block)
|
|
70
|
+
props = Intermediate::Attribute.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
|
|
71
|
+
:name=>role})))
|
|
72
|
+
raise "No opposite available" unless _oppositeProps(raw_props).empty?
|
|
73
|
+
FeatureBlockEvaluator.eval(block, props)
|
|
74
|
+
_build_internal(props)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Add a single unidirectional association.
|
|
78
|
+
# 'role' specifies the name which is used to access the association.
|
|
79
|
+
# 'target_class' specifies the type of objects which can be held by this association.
|
|
80
|
+
#
|
|
81
|
+
# This class method adds the following instance methods, where 'role' is to be
|
|
82
|
+
# replaced by the given role name:
|
|
83
|
+
# class#role # getter
|
|
84
|
+
# class#role=(value) # setter
|
|
85
|
+
#
|
|
86
|
+
def has_one(role, target_class=nil, raw_props={}, &block)
|
|
87
|
+
props = Intermediate::Reference.new(target_class, _ownProps(raw_props).merge({
|
|
88
|
+
:name=>role, :upperBound=>1, :containment=>false}))
|
|
89
|
+
raise "No opposite available" unless _oppositeProps(raw_props).empty?
|
|
90
|
+
FeatureBlockEvaluator.eval(block, props)
|
|
91
|
+
_build_internal(props)
|
|
92
|
+
end
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
94
|
+
# Add an unidirectional _many_ association.
|
|
95
|
+
# 'role' specifies the name which is used to access the attribute.
|
|
96
|
+
# 'target_class' is optional and can be used to fix the type of objects which
|
|
97
|
+
# can be referenced by this association.
|
|
98
|
+
#
|
|
99
|
+
# This class method adds the following instance methods, where 'role' is to be
|
|
100
|
+
# replaced by the given role name:
|
|
101
|
+
# class#addRole(value, index=-1)
|
|
102
|
+
# class#removeRole(value)
|
|
103
|
+
# class#role # getter, returns an array
|
|
104
|
+
# Note that the first letter of the role name is turned into an uppercase
|
|
105
|
+
# for the add and remove methods.
|
|
106
|
+
#
|
|
107
|
+
def has_many(role, target_class=nil, raw_props={}, &block)
|
|
108
|
+
props = Intermediate::Reference.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
|
|
109
|
+
:name=>role, :containment=>false})))
|
|
110
|
+
raise "No opposite available" unless _oppositeProps(raw_props).empty?
|
|
111
|
+
FeatureBlockEvaluator.eval(block, props)
|
|
112
|
+
_build_internal(props)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def contains_one_uni(role, target_class=nil, raw_props={}, &block)
|
|
116
|
+
props = Intermediate::Reference.new(target_class, _ownProps(raw_props).merge({
|
|
117
|
+
:name=>role, :upperBound=>1, :containment=>true}))
|
|
118
|
+
raise "No opposite available" unless _oppositeProps(raw_props).empty?
|
|
119
|
+
FeatureBlockEvaluator.eval(block, props)
|
|
120
|
+
_build_internal(props)
|
|
121
|
+
end
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
123
|
+
def contains_many_uni(role, target_class=nil, raw_props={}, &block)
|
|
124
|
+
props = Intermediate::Reference.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
|
|
125
|
+
:name=>role, :containment=>true})))
|
|
126
|
+
raise "No opposite available" unless _oppositeProps(raw_props).empty?
|
|
127
|
+
FeatureBlockEvaluator.eval(block, props)
|
|
128
|
+
_build_internal(props)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Add a bidirectional one-to-many association between two classes.
|
|
132
|
+
# The class this method is called on is refered to as _own_class_ in
|
|
133
|
+
# the following.
|
|
134
|
+
#
|
|
135
|
+
# Instances of own_class can use 'own_role' to access _many_ associated instances
|
|
136
|
+
# of type 'target_class'. Instances of 'target_class' can use 'target_role' to
|
|
137
|
+
# access _one_ associated instance of own_class.
|
|
138
|
+
#
|
|
139
|
+
# This class method adds the following instance methods where 'ownRole' and
|
|
140
|
+
# 'targetRole' are to be replaced by the given role names:
|
|
141
|
+
# own_class#addOwnRole(value, index=-1)
|
|
142
|
+
# own_class#removeOwnRole(value)
|
|
143
|
+
# own_class#ownRole
|
|
144
|
+
# target_class#targetRole
|
|
145
|
+
# target_class#targetRole=(value)
|
|
146
|
+
# Note that the first letter of the role name is turned into an uppercase
|
|
147
|
+
# for the add and remove methods.
|
|
148
|
+
#
|
|
149
|
+
# When an element is added/set on either side, this element also receives the element
|
|
150
|
+
# is is added to as a new element.
|
|
151
|
+
#
|
|
152
|
+
def one_to_many(target_role, target_class, own_role, raw_props={}, &block)
|
|
153
|
+
props1 = Intermediate::Reference.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
|
|
154
|
+
:name=>target_role, :containment=>false})))
|
|
155
|
+
props2 = Intermediate::Reference.new(self, _oppositeProps(raw_props).merge({
|
|
156
|
+
:name=>own_role, :upperBound=>1, :containment=>false}))
|
|
157
|
+
FeatureBlockEvaluator.eval(block, props1, props2)
|
|
158
|
+
_build_internal(props1, props2)
|
|
159
|
+
end
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
161
|
+
def contains_many(target_role, target_class, own_role, raw_props={}, &block)
|
|
162
|
+
props1 = Intermediate::Reference.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
|
|
163
|
+
:name=>target_role, :containment=>true})))
|
|
164
|
+
props2 = Intermediate::Reference.new(self, _oppositeProps(raw_props).merge({
|
|
165
|
+
:name=>own_role, :upperBound=>1, :containment=>false}))
|
|
166
|
+
FeatureBlockEvaluator.eval(block, props1, props2)
|
|
167
|
+
_build_internal(props1, props2)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# This is the inverse of one_to_many provided for convenience.
|
|
171
|
+
def many_to_one(target_role, target_class, own_role, raw_props={}, &block)
|
|
172
|
+
props1 = Intermediate::Reference.new(target_class, _ownProps(raw_props).merge({
|
|
173
|
+
:name=>target_role, :upperBound=>1, :containment=>false}))
|
|
174
|
+
props2 = Intermediate::Reference.new(self, _setManyUpperBound(_oppositeProps(raw_props).merge({
|
|
175
|
+
:name=>own_role, :containment=>false})))
|
|
176
|
+
FeatureBlockEvaluator.eval(block, props1, props2)
|
|
177
|
+
_build_internal(props1, props2)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Add a bidirectional many-to-many association between two classes.
|
|
181
|
+
# The class this method is called on is refered to as _own_class_ in
|
|
182
|
+
# the following.
|
|
183
|
+
#
|
|
184
|
+
# Instances of own_class can use 'own_role' to access _many_ associated instances
|
|
185
|
+
# of type 'target_class'. Instances of 'target_class' can use 'target_role' to
|
|
186
|
+
# access _many_ associated instances of own_class.
|
|
187
|
+
#
|
|
188
|
+
# This class method adds the following instance methods where 'ownRole' and
|
|
189
|
+
# 'targetRole' are to be replaced by the given role names:
|
|
190
|
+
# own_class#addOwnRole(value, index=-1)
|
|
191
|
+
# own_class#removeOwnRole(value)
|
|
192
|
+
# own_class#ownRole
|
|
193
|
+
# target_class#addTargetRole
|
|
194
|
+
# target_class#removeTargetRole=(value)
|
|
195
|
+
# target_class#targetRole
|
|
196
|
+
# Note that the first letter of the role name is turned into an uppercase
|
|
197
|
+
# for the add and remove methods.
|
|
198
|
+
#
|
|
199
|
+
# When an element is added on either side, this element also receives the element
|
|
200
|
+
# is is added to as a new element.
|
|
201
|
+
#
|
|
202
|
+
def many_to_many(target_role, target_class, own_role, raw_props={}, &block)
|
|
203
|
+
props1 = Intermediate::Reference.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
|
|
204
|
+
:name=>target_role, :containment=>false})))
|
|
205
|
+
props2 = Intermediate::Reference.new(self, _setManyUpperBound(_oppositeProps(raw_props).merge({
|
|
206
|
+
:name=>own_role, :containment=>false})))
|
|
207
|
+
FeatureBlockEvaluator.eval(block, props1, props2)
|
|
208
|
+
_build_internal(props1, props2)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Add a bidirectional one-to-one association between two classes.
|
|
212
|
+
# The class this method is called on is refered to as _own_class_ in
|
|
213
|
+
# the following.
|
|
214
|
+
#
|
|
215
|
+
# Instances of own_class can use 'own_role' to access _one_ associated instance
|
|
216
|
+
# of type 'target_class'. Instances of 'target_class' can use 'target_role' to
|
|
217
|
+
# access _one_ associated instance of own_class.
|
|
218
|
+
#
|
|
219
|
+
# This class method adds the following instance methods where 'ownRole' and
|
|
220
|
+
# 'targetRole' are to be replaced by the given role names:
|
|
221
|
+
# own_class#ownRole
|
|
222
|
+
# own_class#ownRole=(value)
|
|
223
|
+
# target_class#targetRole
|
|
224
|
+
# target_class#targetRole=(value)
|
|
225
|
+
#
|
|
226
|
+
# When an element is set on either side, this element also receives the element
|
|
227
|
+
# is is added to as the new element.
|
|
228
|
+
#
|
|
229
|
+
def one_to_one(target_role, target_class, own_role, raw_props={}, &block)
|
|
230
|
+
props1 = Intermediate::Reference.new(target_class, _ownProps(raw_props).merge({
|
|
231
|
+
:name=>target_role, :upperBound=>1, :containment=>false}))
|
|
232
|
+
props2 = Intermediate::Reference.new(self, _oppositeProps(raw_props).merge({
|
|
233
|
+
:name=>own_role, :upperBound=>1, :containment=>false}))
|
|
234
|
+
FeatureBlockEvaluator.eval(block, props1, props2)
|
|
235
|
+
_build_internal(props1, props2)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def contains_one(target_role, target_class, own_role, raw_props={}, &block)
|
|
239
|
+
props1 = Intermediate::Reference.new(target_class, _ownProps(raw_props).merge({
|
|
240
|
+
:name=>target_role, :upperBound=>1, :containment=>true}))
|
|
241
|
+
props2 = Intermediate::Reference.new(self, _oppositeProps(raw_props).merge({
|
|
242
|
+
:name=>own_role, :upperBound=>1, :containment=>false}))
|
|
243
|
+
FeatureBlockEvaluator.eval(block, props1, props2)
|
|
244
|
+
_build_internal(props1, props2)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def _metamodel_description # :nodoc:
|
|
248
|
+
@metamodel_description ||= []
|
|
249
249
|
end
|
|
250
250
|
|
|
251
251
|
def _add_metamodel_description(desc) # :nodoc
|
|
252
|
-
|
|
252
|
+
@metamodel_description ||= []
|
|
253
253
|
@metamodelDescriptionByName ||= {}
|
|
254
254
|
@metamodel_description.delete(@metamodelDescriptionByName[desc.value(:name)])
|
|
255
255
|
@metamodel_description << desc
|
|
@@ -263,146 +263,147 @@ module BuilderExtensions
|
|
|
263
263
|
def _abstract_class
|
|
264
264
|
@abstract || false
|
|
265
265
|
end
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
266
|
+
|
|
267
|
+
def inherited(c)
|
|
268
|
+
c.send(:include, c.const_set(:ClassModule, Module.new))
|
|
269
269
|
MetamodelBuilder::ConstantOrderHelper.classCreated(c)
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
protected
|
|
273
|
+
|
|
274
|
+
# Central builder method
|
|
275
|
+
#
|
|
276
|
+
def _build_internal(props1, props2=nil)
|
|
277
|
+
_add_metamodel_description(props1)
|
|
278
|
+
if props1.many?
|
|
279
|
+
_build_many_methods(props1, props2)
|
|
280
|
+
else
|
|
281
|
+
_build_one_methods(props1, props2)
|
|
282
|
+
end
|
|
283
|
+
if props2
|
|
284
|
+
# this is a bidirectional reference
|
|
285
|
+
props1.opposite, props2.opposite = props2, props1
|
|
286
|
+
other_class = props1.impl_type
|
|
287
|
+
other_class._add_metamodel_description(props2)
|
|
288
|
+
raise "Internal error: second description must be a reference description" \
|
|
289
|
+
unless props2.reference?
|
|
290
|
+
if props2.many?
|
|
291
|
+
other_class._build_many_methods(props2, props1)
|
|
292
|
+
else
|
|
293
|
+
other_class._build_one_methods(props2, props1)
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# To-One association methods
|
|
299
|
+
#
|
|
300
|
+
def _build_one_methods(props, other_props=nil)
|
|
301
|
+
name = props.value(:name)
|
|
302
|
+
other_role = other_props && other_props.value(:name)
|
|
303
303
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
304
|
+
if props.value(:derived)
|
|
305
|
+
build_derived_method(name, props, :one)
|
|
306
|
+
else
|
|
307
|
+
@@one_read_builder ||= ERB.new <<-CODE
|
|
308
|
+
|
|
309
|
+
def <%= name %>
|
|
310
|
+
<% if !props.reference? && props.value(:defaultValueLiteral) %>
|
|
311
|
+
<% defVal = props.value(:defaultValueLiteral) %>
|
|
312
|
+
<% check_default_value_literal(defVal, props) %>
|
|
313
|
+
<% defVal = '"'+defVal+'"' if props.impl_type == String %>
|
|
314
|
+
<% defVal = ':'+defVal if props.impl_type.is_a?(DataTypes::Enum) && props.impl_type != DataTypes::Boolean %>
|
|
315
|
+
@<%= name %>.nil? ? <%= defVal %> : @<%= name %>
|
|
316
|
+
<% else %>
|
|
317
|
+
@<%= name %>
|
|
318
|
+
<% end %>
|
|
319
|
+
end
|
|
320
|
+
alias get<%= firstToUpper(name) %> <%= name %>
|
|
320
321
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
322
|
+
CODE
|
|
323
|
+
self::ClassModule.module_eval(@@one_read_builder.result(binding))
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
if props.value(:changeable)
|
|
327
|
+
@@one_write_builder ||= ERB.new <<-CODE
|
|
328
|
+
|
|
329
|
+
def <%= name %>=(val)
|
|
330
|
+
return if val == @<%= name %>
|
|
331
|
+
<%= type_check_code("val", props) %>
|
|
332
|
+
oldval = @<%= name %>
|
|
333
|
+
@<%= name %> = val
|
|
334
|
+
<% if other_role %>
|
|
335
|
+
oldval._unregister<%= firstToUpper(other_role) %>(self) unless oldval.nil? || oldval.is_a?(MMGeneric)
|
|
336
|
+
val._register<%= firstToUpper(other_role) %>(self) unless val.nil? || val.is_a?(MMGeneric)
|
|
337
|
+
<% end %>
|
|
338
|
+
end
|
|
339
|
+
alias set<%= firstToUpper(name) %> <%= name %>=
|
|
339
340
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
341
|
+
def _register<%= firstToUpper(name) %>(val)
|
|
342
|
+
<% if other_role %>
|
|
343
|
+
@<%= name %>._unregister<%= firstToUpper(other_role) %>(self) unless @<%= name %>.nil? || @<%= name %>.is_a?(MMGeneric)
|
|
344
|
+
<% end %>
|
|
345
|
+
@<%= name %> = val
|
|
346
|
+
end
|
|
346
347
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
348
|
+
def _unregister<%= firstToUpper(name) %>(val)
|
|
349
|
+
@<%= name %> = nil
|
|
350
|
+
end
|
|
350
351
|
|
|
351
|
-
|
|
352
|
-
|
|
352
|
+
CODE
|
|
353
|
+
self::ClassModule.module_eval(@@one_write_builder.result(binding))
|
|
353
354
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
# To-Many association methods
|
|
359
|
+
#
|
|
360
|
+
def _build_many_methods(props, other_props=nil)
|
|
361
|
+
name = props.value(:name)
|
|
362
|
+
other_role = other_props && other_props.value(:name)
|
|
362
363
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
364
|
+
if props.value(:derived)
|
|
365
|
+
build_derived_method(name, props, :many)
|
|
366
|
+
else
|
|
367
|
+
@@many_read_builder ||= ERB.new <<-CODE
|
|
368
|
+
|
|
369
|
+
def <%= name %>
|
|
370
|
+
( @<%= name %> ? @<%= name %>.dup : [] )
|
|
371
|
+
end
|
|
372
|
+
alias get<%= firstToUpper(name) %> <%= name %>
|
|
373
|
+
|
|
374
|
+
CODE
|
|
375
|
+
self::ClassModule.module_eval(@@many_read_builder.result(binding))
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
if props.value(:changeable)
|
|
379
|
+
@@many_write_builder ||= ERB.new <<-CODE
|
|
380
|
+
|
|
381
|
+
def add<%= firstToUpper(name) %>(val, index=-1)
|
|
382
|
+
@<%= name %> = [] unless @<%= name %>
|
|
383
|
+
return if val.nil? || (@<%= name %>.any?{|e| e.object_id == val.object_id} && (val.is_a?(MMBase) || val.is_a?(MMGeneric)))
|
|
384
|
+
<%= type_check_code("val", props) %>
|
|
385
|
+
@<%= name %>.insert(index, val)
|
|
386
|
+
<% if other_role %>
|
|
387
|
+
val._register<%= firstToUpper(other_role) %>(self) unless val.is_a?(MMGeneric)
|
|
388
|
+
<% end %>
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def remove<%= firstToUpper(name) %>(val)
|
|
392
|
+
@<%= name %> = [] unless @<%= name %>
|
|
393
|
+
@<%= name %>.each_with_index do |e,i|
|
|
394
|
+
if e.object_id == val.object_id
|
|
395
|
+
@<%= name %>.delete_at(i)
|
|
396
|
+
<% if other_role %>
|
|
397
|
+
val._unregister<%= firstToUpper(other_role) %>(self) unless val.is_a?(MMGeneric)
|
|
398
|
+
<% end %>
|
|
399
|
+
return
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
end
|
|
402
403
|
|
|
403
404
|
def <%= name %>=(val)
|
|
404
405
|
return if val.nil?
|
|
405
|
-
raise _assignmentTypeError(self, val,
|
|
406
|
+
raise _assignmentTypeError(self, val, Enumerable) unless val.is_a? Enumerable
|
|
406
407
|
get<%= firstToUpper(name) %>.each {|e|
|
|
407
408
|
remove<%= firstToUpper(name) %>(e)
|
|
408
409
|
}
|
|
@@ -410,7 +411,7 @@ module BuilderExtensions
|
|
|
410
411
|
add<%= firstToUpper(name) %>(v)
|
|
411
412
|
}
|
|
412
413
|
end
|
|
413
|
-
|
|
414
|
+
alias set<%= firstToUpper(name) %> <%= name %>=
|
|
414
415
|
|
|
415
416
|
def _register<%= firstToUpper(name) %>(val)
|
|
416
417
|
@<%= name %> = [] unless @<%= name %>
|
|
@@ -421,63 +422,86 @@ module BuilderExtensions
|
|
|
421
422
|
@<%= name %>.delete val
|
|
422
423
|
end
|
|
423
424
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
425
|
+
CODE
|
|
426
|
+
self::ClassModule.module_eval(@@many_write_builder.result(binding))
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
end
|
|
429
430
|
|
|
430
|
-
|
|
431
|
+
private
|
|
432
|
+
|
|
433
|
+
def build_derived_method(name, props, kind)
|
|
434
|
+
raise "Implement method #{name}_derived instead of method #{name}" \
|
|
435
|
+
if (public_instance_methods+protected_instance_methods+private_instance_methods).include?(name)
|
|
436
|
+
@@derived_builder ||= ERB.new <<-CODE
|
|
437
|
+
|
|
438
|
+
def <%= name %>
|
|
439
|
+
raise "Derived feature requires public implementation of method <%= name %>_derived" \
|
|
440
|
+
unless respond_to?(:<%= name+"_derived" %>)
|
|
441
|
+
val = <%= name %>_derived
|
|
442
|
+
<% if kind == :many %>
|
|
443
|
+
raise _assignmentTypeError(self,val,Enumerable) unless val && val.is_a?(Enumerable)
|
|
444
|
+
val.each do |v|
|
|
445
|
+
<%= type_check_code("v", props) %>
|
|
446
|
+
end
|
|
447
|
+
<% else %>
|
|
448
|
+
<%= type_check_code("val", props) %>
|
|
449
|
+
<% end %>
|
|
450
|
+
val
|
|
451
|
+
end
|
|
452
|
+
alias get<%= firstToUpper(name) %> <%= name %>
|
|
453
|
+
#TODO final_method :<%= name %>
|
|
454
|
+
|
|
455
|
+
CODE
|
|
456
|
+
self::ClassModule.module_eval(@@derived_builder.result(binding))
|
|
457
|
+
end
|
|
431
458
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
def _ownProps(props)
|
|
475
|
-
Hash[*(props.select{|k,v| !(k.to_s =~ /^opposite_/)}.flatten)]
|
|
459
|
+
def check_default_value_literal(literal, props)
|
|
460
|
+
return if literal.nil? || props.impl_type == String
|
|
461
|
+
if props.impl_type == Integer
|
|
462
|
+
unless literal =~ /^\d+$/
|
|
463
|
+
raise StandardError.new("Property #{props.value(:name)} can not take value #{literal}, expected an Integer")
|
|
464
|
+
end
|
|
465
|
+
elsif props.impl_type == Float
|
|
466
|
+
unless literal =~ /^\d+\.\d+$/
|
|
467
|
+
raise StandardError.new("Property #{props.value(:name)} can not take value #{literal}, expected a Float")
|
|
468
|
+
end
|
|
469
|
+
elsif props.impl_type == RGen::MetamodelBuilder::DataTypes::Boolean
|
|
470
|
+
unless ["true", "false"].include?(literal)
|
|
471
|
+
raise StandardError.new("Property #{props.value(:name)} can not take value #{literal}, expected true or false")
|
|
472
|
+
end
|
|
473
|
+
elsif props.impl_type.is_a?(RGen::MetamodelBuilder::DataTypes::Enum)
|
|
474
|
+
unless props.impl_type.literals.include?(literal.to_sym)
|
|
475
|
+
raise StandardError.new("Property #{props.value(:name)} can not take value #{literal}, expected one of #{props.impl_type.literals_as_strings.join(', ')}")
|
|
476
|
+
end
|
|
477
|
+
else
|
|
478
|
+
raise StandardError.new("Unkown type "+props.impl_type.to_s)
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
def type_check_code(varname, props)
|
|
483
|
+
code = ""
|
|
484
|
+
if props.impl_type.is_a?(Class)
|
|
485
|
+
code << "unless #{varname}.nil? || #{varname}.is_a?(#{props.impl_type}) || #{varname}.is_a?(MMGeneric)\n"
|
|
486
|
+
expected = props.impl_type.to_s
|
|
487
|
+
elsif props.impl_type.is_a?(RGen::MetamodelBuilder::DataTypes::Enum)
|
|
488
|
+
code << "unless #{varname}.nil? || [#{props.impl_type.literals_as_strings.join(',')}].include?(#{varname}) || #{varname}.is_a?(MMGeneric)\n"
|
|
489
|
+
expected = "["+props.impl_type.literals_as_strings.join(',')+"]"
|
|
490
|
+
else
|
|
491
|
+
raise StandardError.new("Unkown type "+props.impl_type.to_s)
|
|
492
|
+
end
|
|
493
|
+
code << "raise _assignmentTypeError(self,#{varname},\"#{expected}\")\n"
|
|
494
|
+
code << "end"
|
|
495
|
+
code
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
def _ownProps(props)
|
|
499
|
+
Hash[*(props.select{|k,v| !(k.to_s =~ /^opposite_/)}.flatten)]
|
|
476
500
|
end
|
|
477
501
|
|
|
478
|
-
|
|
502
|
+
def _oppositeProps(props)
|
|
479
503
|
r = {}
|
|
480
|
-
|
|
504
|
+
props.each_pair do |k,v|
|
|
481
505
|
if k.to_s =~ /^opposite_(.*)$/
|
|
482
506
|
r[$1.to_sym] = v
|
|
483
507
|
end
|