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.
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