rgen 0.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/CHANGELOG +28 -0
  2. data/Rakefile +3 -4
  3. data/lib/ea_support/uml13_ea_metamodel.rb +3 -3
  4. data/lib/ea_support/uml13_ea_to_uml13.rb +33 -2
  5. data/lib/ea_support/uml13_to_uml13_ea.rb +7 -0
  6. data/lib/mmgen/mm_ext/ecore_mmgen_ext.rb +4 -4
  7. data/lib/mmgen/templates/metamodel_generator.tpl +143 -143
  8. data/lib/rgen/ecore/ecore.rb +11 -1
  9. data/lib/rgen/ecore/ecore_interface.rb +47 -0
  10. data/lib/rgen/ecore/ecore_to_ruby.rb +166 -0
  11. data/lib/rgen/ecore/{ecore_transformer.rb → ruby_to_ecore.rb} +11 -11
  12. data/lib/rgen/environment.rb +15 -2
  13. data/lib/rgen/fragment/dump_file_cache.rb +63 -0
  14. data/lib/rgen/fragment/fragmented_model.rb +139 -0
  15. data/lib/rgen/fragment/model_fragment.rb +268 -0
  16. data/lib/rgen/instantiator/abstract_xml_instantiator.rb +44 -72
  17. data/lib/rgen/instantiator/default_xml_instantiator.rb +2 -2
  18. data/lib/rgen/instantiator/ecore_xml_instantiator.rb +16 -1
  19. data/lib/rgen/instantiator/json_instantiator.rb +16 -2
  20. data/lib/rgen/instantiator/nodebased_xml_instantiator.rb +118 -138
  21. data/lib/rgen/instantiator/qualified_name_resolver.rb +5 -1
  22. data/lib/rgen/instantiator/reference_resolver.rb +126 -24
  23. data/lib/rgen/instantiator/xmi11_instantiator.rb +6 -2
  24. data/lib/rgen/metamodel_builder.rb +18 -6
  25. data/lib/rgen/metamodel_builder/builder_extensions.rb +431 -407
  26. data/lib/rgen/metamodel_builder/builder_runtime.rb +8 -8
  27. data/lib/rgen/metamodel_builder/constant_order_helper.rb +4 -4
  28. data/lib/rgen/metamodel_builder/data_types.rb +5 -1
  29. data/lib/rgen/metamodel_builder/intermediate/feature.rb +167 -0
  30. data/lib/rgen/metamodel_builder/module_extension.rb +2 -2
  31. data/lib/rgen/model_builder.rb +10 -5
  32. data/lib/rgen/model_builder/builder_context.rb +17 -1
  33. data/lib/rgen/serializer/opposite_reference_filter.rb +18 -0
  34. data/lib/rgen/serializer/qualified_name_provider.rb +45 -0
  35. data/lib/rgen/template_language/template_container.rb +3 -1
  36. data/lib/rgen/{auto_class_creator.rb → util/auto_class_creator.rb} +6 -1
  37. data/lib/rgen/util/cached_glob.rb +67 -0
  38. data/lib/rgen/util/file_cache_map.rb +104 -0
  39. data/lib/rgen/util/file_change_detector.rb +78 -0
  40. data/lib/rgen/{method_delegation.rb → util/method_delegation.rb} +18 -3
  41. data/lib/rgen/{model_comparator.rb → util/model_comparator.rb} +17 -5
  42. data/lib/rgen/{model_comparator_base.rb → util/model_comparator_base.rb} +6 -1
  43. data/lib/rgen/{model_dumper.rb → util/model_dumper.rb} +6 -1
  44. data/lib/rgen/{name_helper.rb → util/name_helper.rb} +6 -1
  45. data/lib/rgen/util/pattern_matcher.rb +329 -0
  46. data/lib/transformers/uml13_to_ecore.rb +103 -60
  47. data/test/ecore_self_test.rb +43 -42
  48. data/test/json_test.rb +15 -0
  49. data/test/metamodel_builder_test.rb +361 -206
  50. data/test/metamodel_from_ecore_test.rb +45 -0
  51. data/test/metamodel_order_test.rb +10 -4
  52. data/test/metamodel_roundtrip_test.rb +2 -2
  53. data/test/metamodel_roundtrip_test/TestModel_Regenerated.rb +1 -1
  54. data/test/metamodel_roundtrip_test/houseMetamodel_Regenerated.ecore +50 -50
  55. data/test/method_delegation_test.rb +9 -9
  56. data/test/model_builder/ecore_internal.rb +19 -9
  57. data/test/model_builder/serializer_test.rb +1 -1
  58. data/test/reference_resolver_test.rb +79 -12
  59. data/test/rgen_test.rb +2 -0
  60. data/test/template_language_test.rb +7 -0
  61. data/test/template_language_test/templates/callback_indent_test/a.tpl +12 -0
  62. data/test/template_language_test/templates/callback_indent_test/b.tpl +5 -0
  63. data/test/testmodel/ea_testmodel_regenerated.xml +588 -583
  64. data/test/transformer_test.rb +3 -3
  65. data/test/util/file_cache_map_test.rb +91 -0
  66. data/test/util/file_cache_map_test/testdir/fileA +1 -0
  67. data/test/util_test.rb +4 -0
  68. data/test/xml_instantiator_test.rb +139 -135
  69. metadata +49 -104
  70. data/lib/rgen/ecore/ecore_instantiator.rb +0 -31
  71. data/lib/rgen/metamodel_builder/metamodel_description.rb +0 -232
  72. data/redist/xmlscan/ChangeLog +0 -1301
  73. data/redist/xmlscan/README +0 -34
  74. data/redist/xmlscan/THANKS +0 -11
  75. data/redist/xmlscan/doc/changes.html +0 -74
  76. data/redist/xmlscan/doc/changes.rd +0 -80
  77. data/redist/xmlscan/doc/en/conformance.html +0 -136
  78. data/redist/xmlscan/doc/en/conformance.rd +0 -152
  79. data/redist/xmlscan/doc/en/manual.html +0 -356
  80. data/redist/xmlscan/doc/en/manual.rd +0 -402
  81. data/redist/xmlscan/doc/ja/conformance.ja.html +0 -118
  82. data/redist/xmlscan/doc/ja/conformance.ja.rd +0 -134
  83. data/redist/xmlscan/doc/ja/manual.ja.html +0 -325
  84. data/redist/xmlscan/doc/ja/manual.ja.rd +0 -370
  85. data/redist/xmlscan/doc/src/Makefile +0 -41
  86. data/redist/xmlscan/doc/src/conformance.rd.src +0 -256
  87. data/redist/xmlscan/doc/src/langsplit.rb +0 -110
  88. data/redist/xmlscan/doc/src/manual.rd.src +0 -614
  89. data/redist/xmlscan/install.rb +0 -41
  90. data/redist/xmlscan/lib/xmlscan/encoding.rb +0 -311
  91. data/redist/xmlscan/lib/xmlscan/htmlscan.rb +0 -289
  92. data/redist/xmlscan/lib/xmlscan/namespace.rb +0 -352
  93. data/redist/xmlscan/lib/xmlscan/parser.rb +0 -299
  94. data/redist/xmlscan/lib/xmlscan/scanner.rb +0 -1109
  95. data/redist/xmlscan/lib/xmlscan/version.rb +0 -22
  96. data/redist/xmlscan/lib/xmlscan/visitor.rb +0 -158
  97. data/redist/xmlscan/lib/xmlscan/xmlchar.rb +0 -441
  98. data/redist/xmlscan/memo/CONFORMANCE +0 -1249
  99. data/redist/xmlscan/memo/PRODUCTIONS +0 -195
  100. data/redist/xmlscan/memo/contentspec.ry +0 -335
  101. data/redist/xmlscan/samples/chibixml.rb +0 -105
  102. data/redist/xmlscan/samples/getxmlchar.rb +0 -122
  103. data/redist/xmlscan/samples/rexml.rb +0 -159
  104. data/redist/xmlscan/samples/xmlbench.rb +0 -88
  105. data/redist/xmlscan/samples/xmlbench/parser/chibixml.rb +0 -22
  106. data/redist/xmlscan/samples/xmlbench/parser/nqxml.rb +0 -29
  107. data/redist/xmlscan/samples/xmlbench/parser/rexml.rb +0 -62
  108. data/redist/xmlscan/samples/xmlbench/parser/xmlparser.rb +0 -22
  109. data/redist/xmlscan/samples/xmlbench/parser/xmlscan-0.0.10.rb +0 -62
  110. data/redist/xmlscan/samples/xmlbench/parser/xmlscan-chibixml.rb +0 -22
  111. data/redist/xmlscan/samples/xmlbench/parser/xmlscan-rexml.rb +0 -22
  112. data/redist/xmlscan/samples/xmlbench/parser/xmlscan.rb +0 -99
  113. data/redist/xmlscan/samples/xmlbench/xmlbench-lib.rb +0 -116
  114. data/redist/xmlscan/samples/xmlconftest.rb +0 -200
  115. data/redist/xmlscan/test.rb +0 -7
  116. data/redist/xmlscan/tests/deftestcase.rb +0 -73
  117. data/redist/xmlscan/tests/runtest.rb +0 -47
  118. data/redist/xmlscan/tests/testall.rb +0 -14
  119. data/redist/xmlscan/tests/testencoding.rb +0 -438
  120. data/redist/xmlscan/tests/testhtmlscan.rb +0 -752
  121. data/redist/xmlscan/tests/testnamespace.rb +0 -457
  122. data/redist/xmlscan/tests/testparser.rb +0 -591
  123. data/redist/xmlscan/tests/testscanner.rb +0 -1749
  124. data/redist/xmlscan/tests/testxmlchar.rb +0 -143
  125. 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
- rd.object.setGeneric(rd.attribute,newval)
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/ecore_instantiator'
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::ECoreInstantiator
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 the proxy class can be used as values in any reference feature
197
- # They can be used instead of the real target elements in case references should be resolved later on
198
- class MMProxy
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/metamodel_description.rb'
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
- include NameHelper
19
+ include Util::NameHelper
20
20
 
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
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
- # 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 = AttributeDescription.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
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
- # 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)
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 = AttributeDescription.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 = ReferenceDescription.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
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
- # 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)
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 = ReferenceDescription.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 = ReferenceDescription.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
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
- def contains_many_uni(role, target_class=nil, raw_props={}, &block)
124
- props = ReferenceDescription.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)
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 = ReferenceDescription.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
154
- :name=>target_role, :containment=>false})))
155
- props2 = ReferenceDescription.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
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
- def contains_many(target_role, target_class, own_role, raw_props={}, &block)
162
- props1 = ReferenceDescription.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
163
- :name=>target_role, :containment=>true})))
164
- props2 = ReferenceDescription.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 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
173
- :name=>target_role, :upperBound=>1, :containment=>false}))
174
- props2 = ReferenceDescription.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)
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 = ReferenceDescription.new(target_class, _setManyUpperBound(_ownProps(raw_props).merge({
204
- :name=>target_role, :containment=>false})))
205
- props2 = ReferenceDescription.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 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
231
- :name=>target_role, :upperBound=>1, :containment=>false}))
232
- props2 = ReferenceDescription.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 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
240
- :name=>target_role, :upperBound=>1, :containment=>true}))
241
- props2 = ReferenceDescription.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 ||= []
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
- @metamodel_description ||= []
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
- def inherited(c)
268
- c.send(:include, c.const_set(:ClassModule, Module.new))
266
+
267
+ def inherited(c)
268
+ c.send(:include, c.const_set(:ClassModule, Module.new))
269
269
  MetamodelBuilder::ConstantOrderHelper.classCreated(c)
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 ReferenceDescription" \
289
- unless props2.is_a?(ReferenceDescription)
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)
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
- 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.is_a?(AttributeDescription) && props.value(:defaultValueLiteral) %>
311
- <% defVal = props.value(:defaultValueLiteral) %>
312
- <% defVal = '"'+defVal+'"' if props.impl_type == String %>
313
- <% defVal = ':'+defVal if props.impl_type.is_a?(DataTypes::Enum) && props.impl_type != DataTypes::Boolean %>
314
- @<%= name %>.nil? ? <%= defVal %> : @<%= name %>
315
- <% else %>
316
- @<%= name %>
317
- <% end %>
318
- end
319
- alias get<%= firstToUpper(name) %> <%= name %>
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
- CODE
322
- self::ClassModule.module_eval(@@one_read_builder.result(binding))
323
- end
324
-
325
- if props.value(:changeable)
326
- @@one_write_builder ||= ERB.new <<-CODE
327
-
328
- def <%= name %>=(val)
329
- return if val == @<%= name %>
330
- <%= type_check_code("val", props) %>
331
- oldval = @<%= name %>
332
- @<%= name %> = val
333
- <% if other_role %>
334
- oldval._unregister<%= firstToUpper(other_role) %>(self) unless oldval.nil? || oldval.is_a?(MMProxy)
335
- val._register<%= firstToUpper(other_role) %>(self) unless val.nil? || val.is_a?(MMProxy)
336
- <% end %>
337
- end
338
- alias set<%= firstToUpper(name) %> <%= name %>=
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
- def _register<%= firstToUpper(name) %>(val)
341
- <% if other_role %>
342
- @<%= name %>._unregister<%= firstToUpper(other_role) %>(self) unless @<%= name %>.nil? || @<%= name %>.is_a?(MMProxy)
343
- <% end %>
344
- @<%= name %> = val
345
- end
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
- def _unregister<%= firstToUpper(name) %>(val)
348
- @<%= name %> = nil
349
- end
348
+ def _unregister<%= firstToUpper(name) %>(val)
349
+ @<%= name %> = nil
350
+ end
350
351
 
351
- CODE
352
- self::ClassModule.module_eval(@@one_write_builder.result(binding))
352
+ CODE
353
+ self::ClassModule.module_eval(@@one_write_builder.result(binding))
353
354
 
354
- end
355
- end
356
-
357
- # To-Many association methods
358
- #
359
- def _build_many_methods(props, other_props=nil)
360
- name = props.value(:name)
361
- other_role = other_props && other_props.value(:name)
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
- if props.value(:derived)
364
- build_derived_method(name, props, :many)
365
- else
366
- @@many_read_builder ||= ERB.new <<-CODE
367
-
368
- def <%= name %>
369
- ( @<%= name %> ? @<%= name %>.dup : [] )
370
- end
371
- alias get<%= firstToUpper(name) %> <%= name %>
372
-
373
- CODE
374
- self::ClassModule.module_eval(@@many_read_builder.result(binding))
375
- end
376
-
377
- if props.value(:changeable)
378
- @@many_write_builder ||= ERB.new <<-CODE
379
-
380
- def add<%= firstToUpper(name) %>(val)
381
- @<%= name %> = [] unless @<%= name %>
382
- return if val.nil? || @<%= name %>.any?{|e| e.object_id == val.object_id}
383
- <%= type_check_code("val", props) %>
384
- @<%= name %>.push val
385
- <% if other_role %>
386
- val._register<%= firstToUpper(other_role) %>(self) unless val.is_a?(MMProxy)
387
- <% end %>
388
- end
389
-
390
- def remove<%= firstToUpper(name) %>(val)
391
- @<%= name %> = [] unless @<%= name %>
392
- @<%= name %>.each_with_index do |e,i|
393
- if e.object_id == val.object_id
394
- @<%= name %>.delete_at(i)
395
- <% if other_role %>
396
- val._unregister<%= firstToUpper(other_role) %>(self) unless val.is_a?(MMProxy)
397
- <% end %>
398
- return
399
- end
400
- end
401
- end
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, Array) unless val.is_a? Array
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
- alias set<%= firstToUpper(name) %> <%= name %>=
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
- CODE
425
- self::ClassModule.module_eval(@@many_write_builder.result(binding))
426
- end
427
-
428
- end
425
+ CODE
426
+ self::ClassModule.module_eval(@@many_write_builder.result(binding))
427
+ end
428
+
429
+ end
429
430
 
430
- private
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
- def build_derived_method(name, props, kind)
433
- raise "Implement method #{name}_derived instead of method #{name}" \
434
- if (public_instance_methods+protected_instance_methods+private_instance_methods).include?(name)
435
- @@derived_builder ||= ERB.new <<-CODE
436
-
437
- def <%= name %>
438
- raise "Derived feature requires public implementation of method <%= name %>_derived" \
439
- unless respond_to?(:<%= name+"_derived" %>)
440
- val = <%= name %>_derived
441
- <% if kind == :many %>
442
- raise _assignmentTypeError(self,val,Array) unless val && val.is_a?(Array)
443
- val.each do |v|
444
- <%= type_check_code("v", props) %>
445
- end
446
- <% else %>
447
- <%= type_check_code("val", props) %>
448
- <% end %>
449
- val
450
- end
451
- alias get<%= firstToUpper(name) %> <%= name %>
452
- #TODO final_method :<%= name %>
453
-
454
- CODE
455
- self::ClassModule.module_eval(@@derived_builder.result(binding))
456
- end
457
-
458
- def type_check_code(varname, props)
459
- code = ""
460
- if props.impl_type.is_a?(Class)
461
- code << "unless #{varname}.nil? || #{varname}.is_a?(#{props.impl_type}) || #{varname}.is_a?(MMProxy)\n"
462
- expected = props.impl_type.to_s
463
- elsif props.impl_type.is_a?(RGen::MetamodelBuilder::DataTypes::Enum)
464
- code << "unless #{varname}.nil? || [#{props.impl_type.literals_as_strings.join(',')}].include?(#{varname})\n"
465
- expected = "["+props.impl_type.literals_as_strings.join(',')+"]"
466
- else
467
- raise StandardError.new("Unkown type "+props.impl_type.to_s)
468
- end
469
- code << "raise _assignmentTypeError(self,#{varname},\"#{expected}\")\n"
470
- code << "end"
471
- code
472
- end
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
- def _oppositeProps(props)
502
+ def _oppositeProps(props)
479
503
  r = {}
480
- props.each_pair do |k,v|
504
+ props.each_pair do |k,v|
481
505
  if k.to_s =~ /^opposite_(.*)$/
482
506
  r[$1.to_sym] = v
483
507
  end