rgen 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. data/CHANGELOG +20 -1
  2. data/MIT-LICENSE +1 -1
  3. data/README +12 -9
  4. data/lib/instantiators/ea_instantiator.rb +36 -0
  5. data/lib/metamodels/uml13_metamodel.rb +559 -0
  6. data/lib/metamodels/uml13_metamodel_ext.rb +26 -0
  7. data/lib/mmgen/metamodel_generator.rb +5 -5
  8. data/lib/mmgen/mm_ext/ecore_ext.rb +95 -0
  9. data/lib/mmgen/mmgen.rb +6 -4
  10. data/lib/mmgen/templates/annotations.tpl +37 -0
  11. data/lib/mmgen/templates/metamodel_generator.tpl +171 -0
  12. data/lib/rgen/ecore/ecore.rb +190 -0
  13. data/lib/rgen/ecore/ecore_instantiator.rb +25 -0
  14. data/lib/rgen/ecore/ecore_transformer.rb +85 -0
  15. data/lib/rgen/environment.rb +9 -24
  16. data/lib/rgen/find_helper.rb +68 -0
  17. data/lib/rgen/{instantiator.rb → instantiator/abstract_instantiator.rb} +6 -2
  18. data/lib/rgen/instantiator/abstract_xml_instantiator.rb +59 -0
  19. data/lib/rgen/instantiator/default_xml_instantiator.rb +117 -0
  20. data/lib/rgen/instantiator/ecore_xml_instantiator.rb +144 -0
  21. data/lib/rgen/instantiator/nodebased_xml_instantiator.rb +157 -0
  22. data/lib/rgen/instantiator/xmi11_instantiator.rb +164 -0
  23. data/lib/rgen/metamodel_builder.rb +103 -9
  24. data/lib/rgen/metamodel_builder/build_helper.rb +26 -4
  25. data/lib/rgen/metamodel_builder/builder_extensions.rb +285 -88
  26. data/lib/rgen/metamodel_builder/builder_runtime.rb +7 -1
  27. data/lib/rgen/metamodel_builder/data_types.rb +67 -0
  28. data/lib/rgen/metamodel_builder/intermediate/annotation.rb +30 -0
  29. data/lib/rgen/metamodel_builder/metamodel_description.rb +232 -0
  30. data/lib/rgen/metamodel_builder/mm_multiple.rb +23 -0
  31. data/lib/rgen/metamodel_builder/module_extension.rb +33 -0
  32. data/lib/rgen/model_comparator.rb +56 -0
  33. data/lib/rgen/model_dumper.rb +5 -5
  34. data/lib/rgen/name_helper.rb +17 -1
  35. data/lib/rgen/template_language.rb +148 -28
  36. data/lib/rgen/template_language/directory_template_container.rb +56 -38
  37. data/lib/rgen/template_language/output_handler.rb +93 -77
  38. data/lib/rgen/template_language/template_container.rb +186 -143
  39. data/lib/rgen/transformer.rb +19 -14
  40. data/lib/transformers/uml13_to_ecore.rb +75 -0
  41. data/redist/xmlscan/ChangeLog +1301 -0
  42. data/redist/xmlscan/README +34 -0
  43. data/redist/xmlscan/THANKS +11 -0
  44. data/redist/xmlscan/doc/changes.html +74 -0
  45. data/redist/xmlscan/doc/changes.rd +80 -0
  46. data/redist/xmlscan/doc/en/conformance.html +136 -0
  47. data/redist/xmlscan/doc/en/conformance.rd +152 -0
  48. data/redist/xmlscan/doc/en/manual.html +356 -0
  49. data/redist/xmlscan/doc/en/manual.rd +402 -0
  50. data/redist/xmlscan/doc/ja/conformance.ja.html +118 -0
  51. data/redist/xmlscan/doc/ja/conformance.ja.rd +134 -0
  52. data/redist/xmlscan/doc/ja/manual.ja.html +325 -0
  53. data/redist/xmlscan/doc/ja/manual.ja.rd +370 -0
  54. data/redist/xmlscan/doc/src/Makefile +41 -0
  55. data/redist/xmlscan/doc/src/conformance.rd.src +256 -0
  56. data/redist/xmlscan/doc/src/langsplit.rb +110 -0
  57. data/redist/xmlscan/doc/src/manual.rd.src +614 -0
  58. data/redist/xmlscan/install.rb +41 -0
  59. data/redist/xmlscan/lib/xmlscan/encoding.rb +311 -0
  60. data/redist/xmlscan/lib/xmlscan/htmlscan.rb +289 -0
  61. data/redist/xmlscan/lib/xmlscan/namespace.rb +352 -0
  62. data/redist/xmlscan/lib/xmlscan/parser.rb +299 -0
  63. data/redist/xmlscan/lib/xmlscan/scanner.rb +1109 -0
  64. data/redist/xmlscan/lib/xmlscan/version.rb +22 -0
  65. data/redist/xmlscan/lib/xmlscan/visitor.rb +158 -0
  66. data/redist/xmlscan/lib/xmlscan/xmlchar.rb +441 -0
  67. data/redist/xmlscan/memo/CONFORMANCE +1249 -0
  68. data/redist/xmlscan/memo/PRODUCTIONS +195 -0
  69. data/redist/xmlscan/memo/contentspec.ry +335 -0
  70. data/redist/xmlscan/samples/chibixml.rb +105 -0
  71. data/redist/xmlscan/samples/getxmlchar.rb +122 -0
  72. data/redist/xmlscan/samples/rexml.rb +159 -0
  73. data/redist/xmlscan/samples/xmlbench.rb +88 -0
  74. data/redist/xmlscan/samples/xmlbench/parser/chibixml.rb +22 -0
  75. data/redist/xmlscan/samples/xmlbench/parser/nqxml.rb +29 -0
  76. data/redist/xmlscan/samples/xmlbench/parser/rexml.rb +62 -0
  77. data/redist/xmlscan/samples/xmlbench/parser/xmlparser.rb +22 -0
  78. data/redist/xmlscan/samples/xmlbench/parser/xmlscan-0.0.10.rb +62 -0
  79. data/redist/xmlscan/samples/xmlbench/parser/xmlscan-chibixml.rb +22 -0
  80. data/redist/xmlscan/samples/xmlbench/parser/xmlscan-rexml.rb +22 -0
  81. data/redist/xmlscan/samples/xmlbench/parser/xmlscan.rb +99 -0
  82. data/redist/xmlscan/samples/xmlbench/xmlbench-lib.rb +116 -0
  83. data/redist/xmlscan/samples/xmlconftest.rb +200 -0
  84. data/redist/xmlscan/test.rb +7 -0
  85. data/redist/xmlscan/tests/deftestcase.rb +73 -0
  86. data/redist/xmlscan/tests/runtest.rb +47 -0
  87. data/redist/xmlscan/tests/testall.rb +14 -0
  88. data/redist/xmlscan/tests/testencoding.rb +438 -0
  89. data/redist/xmlscan/tests/testhtmlscan.rb +752 -0
  90. data/redist/xmlscan/tests/testnamespace.rb +457 -0
  91. data/redist/xmlscan/tests/testparser.rb +591 -0
  92. data/redist/xmlscan/tests/testscanner.rb +1749 -0
  93. data/redist/xmlscan/tests/testxmlchar.rb +143 -0
  94. data/redist/xmlscan/tests/visitor.rb +34 -0
  95. data/test/array_extensions_test.rb +2 -2
  96. data/test/ea_instantiator_test.rb +41 -0
  97. data/test/ecore_self_test.rb +53 -0
  98. data/test/environment_test.rb +11 -6
  99. data/test/metamodel_builder_test.rb +404 -245
  100. data/test/metamodel_roundtrip_test.rb +52 -0
  101. data/test/metamodel_roundtrip_test/TestModel.rb +65 -0
  102. data/test/metamodel_roundtrip_test/TestModel_Regenerated.rb +64 -0
  103. data/test/metamodel_roundtrip_test/houseMetamodel.ecore +32 -0
  104. data/test/metamodel_roundtrip_test/houseMetamodel_from_ecore.rb +39 -0
  105. data/test/rgen_test.rb +3 -3
  106. data/test/template_language_test.rb +65 -39
  107. data/test/template_language_test/expected_result.txt +24 -3
  108. data/test/template_language_test/templates/code/array.tpl +11 -0
  109. data/test/template_language_test/templates/content/author.tpl +7 -0
  110. data/test/template_language_test/templates/content/chapter.tpl +1 -1
  111. data/test/template_language_test/templates/root.tpl +17 -8
  112. data/test/template_language_test/testout.txt +24 -3
  113. data/test/testmodel/class_model_checker.rb +119 -0
  114. data/test/{xmi_instantiator_test/testmodel.eap → testmodel/ea_testmodel.eap} +0 -0
  115. data/test/{xmi_instantiator_test/testmodel.xml → testmodel/ea_testmodel.xml} +81 -14
  116. data/test/testmodel/ea_testmodel_partial.xml +317 -0
  117. data/test/testmodel/ecore_model_checker.rb +101 -0
  118. data/test/testmodel/manual_testmodel.xml +22 -0
  119. data/test/testmodel/object_model_checker.rb +67 -0
  120. data/test/transformer_test.rb +18 -10
  121. data/test/xml_instantiator_test.rb +81 -8
  122. data/test/xml_instantiator_test/simple_ecore_model_checker.rb +94 -0
  123. data/test/xml_instantiator_test/simple_xmi_ecore_instantiator.rb +53 -0
  124. data/test/xml_instantiator_test/simple_xmi_metamodel.rb +49 -0
  125. data/test/xml_instantiator_test/simple_xmi_to_ecore.rb +75 -0
  126. metadata +126 -28
  127. data/lib/ea/xmi_class_instantiator.rb +0 -46
  128. data/lib/ea/xmi_helper.rb +0 -26
  129. data/lib/ea/xmi_metamodel.rb +0 -34
  130. data/lib/ea/xmi_object_instantiator.rb +0 -46
  131. data/lib/ea/xmi_to_classmodel.rb +0 -78
  132. data/lib/ea/xmi_to_objectmodel.rb +0 -92
  133. data/lib/mmgen/mm_ext/uml_classmodel_ext.rb +0 -71
  134. data/lib/mmgen/templates/uml_classmodel.tpl +0 -63
  135. data/lib/rgen/xml_instantiator.rb +0 -132
  136. data/lib/uml/objectmodel_instantiator.rb +0 -53
  137. data/lib/uml/uml_classmodel.rb +0 -92
  138. data/lib/uml/uml_objectmodel.rb +0 -65
  139. data/test/metamodel_generator_test.rb +0 -44
  140. data/test/metamodel_generator_test/TestModel.rb +0 -40
  141. data/test/metamodel_generator_test/expected_result.txt +0 -40
  142. data/test/xmi_class_instantiator_test.rb +0 -24
  143. data/test/xmi_instantiator_test/class_model_checker.rb +0 -97
  144. data/test/xmi_object_instantiator_test.rb +0 -65
  145. data/test/xml_instantiator_test/testmodel.xml +0 -7
@@ -11,16 +11,38 @@ class BuildHelper
11
11
  include NameHelper
12
12
 
13
13
  def self.build(mod,bnd,tpl)
14
- mod.module_eval ERB.new(tpl).result(BuildHelper.new(bnd).bnd)
14
+ mod.module_eval ERB.new(tpl).result(BuildHelper.new(mod, bnd).bnd)
15
15
  end
16
- def initialize(bnd)
16
+ def initialize(mod, bnd)
17
17
  @outer_binding = bnd
18
+ @mod = mod
18
19
  end
19
20
  def bnd
20
21
  binding
21
22
  end
22
- def method_missing(m)
23
- eval("#{m}",@outer_binding)
23
+ def method_missing(m, *args)
24
+ if args.empty?
25
+ eval("#{m}",@outer_binding)
26
+ else
27
+ @mod.instance_eval do
28
+ send(m,*args)
29
+ end
30
+ end
31
+ end
32
+ def type_check_code(varname, props)
33
+ code = ""
34
+ if props.impl_type.is_a?(Class)
35
+ code << "unless #{varname}.nil? or #{varname}.is_a? #{props.impl_type}\n"
36
+ expected = props.impl_type.to_s
37
+ elsif props.impl_type.is_a?(RGen::MetamodelBuilder::DataTypes::Enum)
38
+ code << "unless #{varname}.nil? or [#{props.impl_type.literals_as_strings.join(',')}].include?(#{varname})\n"
39
+ expected = "["+props.impl_type.literals_as_strings.join(',')+"]"
40
+ else
41
+ raise StandardError.new("Unkown type "+props.impl_type.to_s)
42
+ end
43
+ code << "raise _assignmentTypeError(self,#{varname},\"#{expected}\")\n"
44
+ code << "end"
45
+ code
24
46
  end
25
47
  end
26
48
 
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'erb'
5
5
  require 'rgen/metamodel_builder/build_helper'
6
+ require 'rgen/metamodel_builder/metamodel_description.rb'
6
7
 
7
8
  module RGen
8
9
 
@@ -16,19 +17,50 @@ module MetamodelBuilder
16
17
  # See MetamodelBuilder for an example.
17
18
  #
18
19
  module BuilderExtensions
20
+ include NameHelper
19
21
 
22
+ class FeatureBlockEvaluator
23
+ def self.eval(block, props1, props2=nil)
24
+ return unless block
25
+ e = self.new(props1, props2)
26
+ e.instance_eval(&block)
27
+ end
28
+ def initialize(props1, props2)
29
+ @props1, @props2 = props1, props2
30
+ end
31
+ def annotation(hash)
32
+ @props1.annotations << Intermediate::Annotation.new(hash)
33
+ end
34
+ def opposite_annotation(hash)
35
+ raise "No opposite available" unless @props2
36
+ @props2.annotations << Intermediate::Annotation.new(hash)
37
+ end
38
+ end
39
+
40
+ def has_attr(role, target_class=nil, raw_props={}, &block)
41
+ props = AttributeDescription.new(target_class, _ownProps(raw_props).merge({
42
+ :name=>role, :upperBound=>1}))
43
+ raise "No opposite available" unless _oppositeProps(raw_props).empty?
44
+ FeatureBlockEvaluator.eval(block, props)
45
+ _build_internal(props)
46
+ end
47
+
20
48
  # Add a single attribute or unidirectional association.
21
49
  # 'role' specifies the name which is used to access the attribute.
22
- # 'target_class' is optional and can be used to fix the type of objects which
23
- # can be held by this attribute.
50
+ # 'target_class' specifies the type of objects which can be held by this attribute.
51
+ # If no target class is given, String will be default.
24
52
  #
25
53
  # This class method adds the following instance methods, where 'role' is to be
26
54
  # replaced by the given role name:
27
55
  # class#role # getter
28
56
  # class#role=(value) # setter
29
57
  #
30
- def has_one(role, target_class=nil)
31
- has_one_internal(role, target_class)
58
+ def has_one(role, target_class=nil, raw_props={}, &block)
59
+ props = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
60
+ :name=>role, :upperBound=>1, :containment=>false}))
61
+ raise "No opposite available" unless _oppositeProps(raw_props).empty?
62
+ FeatureBlockEvaluator.eval(block, props)
63
+ _build_internal(props)
32
64
  end
33
65
 
34
66
  # Add an unidirectional _many_ association.
@@ -44,8 +76,28 @@ module BuilderExtensions
44
76
  # Note that the first letter of the role name is turned into an uppercase
45
77
  # for the add and remove methods.
46
78
  #
47
- def has_many(role, target_class=nil)
48
- has_many_internal(role, target_class)
79
+ def has_many(role, target_class=nil, raw_props={}, &block)
80
+ props = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
81
+ :name=>role, :upperBound=>-1, :containment=>false}))
82
+ raise "No opposite available" unless _oppositeProps(raw_props).empty?
83
+ FeatureBlockEvaluator.eval(block, props)
84
+ _build_internal(props)
85
+ end
86
+
87
+ def contains_one_uni(role, target_class=nil, raw_props={}, &block)
88
+ props = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
89
+ :name=>role, :upperBound=>1, :containment=>true}))
90
+ raise "No opposite available" unless _oppositeProps(raw_props).empty?
91
+ FeatureBlockEvaluator.eval(block, props)
92
+ _build_internal(props)
93
+ end
94
+
95
+ def contains_many_uni(role, target_class=nil, raw_props={}, &block)
96
+ props = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
97
+ :name=>role, :upperBound=>-1, :containment=>true}))
98
+ raise "No opposite available" unless _oppositeProps(raw_props).empty?
99
+ FeatureBlockEvaluator.eval(block, props)
100
+ _build_internal(props)
49
101
  end
50
102
 
51
103
  # Add a bidirectional one-to-many association between two classes.
@@ -69,15 +121,32 @@ module BuilderExtensions
69
121
  # When an element is added/set on either side, this element also receives the element
70
122
  # is is added to as a new element.
71
123
  #
72
- def one_to_many(own_role, target_class, target_role)
73
- has_many_internal(own_role,target_class,target_role,:one)
74
- target_class.has_one_internal(target_role,self,own_role,:many)
124
+ def one_to_many(target_role, target_class, own_role, raw_props={}, &block)
125
+ props1 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
126
+ :name=>target_role, :upperBound=>-1, :containment=>false}))
127
+ props2 = ReferenceDescription.new(self, _oppositeProps(raw_props).merge({
128
+ :name=>own_role, :upperBound=>1, :containment=>false}))
129
+ FeatureBlockEvaluator.eval(block, props1, props2)
130
+ _build_internal(props1, props2)
131
+ end
132
+
133
+ def contains_many(target_role, target_class, own_role, raw_props={}, &block)
134
+ props1 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
135
+ :name=>target_role, :upperBound=>-1, :containment=>true}))
136
+ props2 = ReferenceDescription.new(self, _oppositeProps(raw_props).merge({
137
+ :name=>own_role, :upperBound=>1, :containment=>false}))
138
+ FeatureBlockEvaluator.eval(block, props1, props2)
139
+ _build_internal(props1, props2)
75
140
  end
76
141
 
77
142
  # This is the inverse of one_to_many provided for convenience.
78
- def many_to_one(own_role, target_class, target_role)
79
- has_one_internal(own_role,target_class,target_role,:many)
80
- target_class.has_many_internal(target_role,self,own_role,:one)
143
+ def many_to_one(target_role, target_class, own_role, raw_props={}, &block)
144
+ props1 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
145
+ :name=>target_role, :upperBound=>1, :containment=>false}))
146
+ props2 = ReferenceDescription.new(self, _oppositeProps(raw_props).merge({
147
+ :name=>own_role, :upperBound=>-1, :containment=>false}))
148
+ FeatureBlockEvaluator.eval(block, props1, props2)
149
+ _build_internal(props1, props2)
81
150
  end
82
151
 
83
152
  # Add a bidirectional many-to-many association between two classes.
@@ -102,9 +171,13 @@ module BuilderExtensions
102
171
  # When an element is added on either side, this element also receives the element
103
172
  # is is added to as a new element.
104
173
  #
105
- def many_to_many(own_role, target_class, target_role)
106
- has_many_internal(own_role,target_class,target_role,:many)
107
- target_class.has_many_internal(target_role,self,own_role,:many)
174
+ def many_to_many(target_role, target_class, own_role, raw_props={}, &block)
175
+ props1 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
176
+ :name=>target_role, :upperBound=>-1, :containment=>false}))
177
+ props2 = ReferenceDescription.new(self, _oppositeProps(raw_props).merge({
178
+ :name=>own_role, :upperBound=>-1, :containment=>false}))
179
+ FeatureBlockEvaluator.eval(block, props1, props2)
180
+ _build_internal(props1, props2)
108
181
  end
109
182
 
110
183
  # Add a bidirectional one-to-one association between two classes.
@@ -125,93 +198,217 @@ module BuilderExtensions
125
198
  # When an element is set on either side, this element also receives the element
126
199
  # is is added to as the new element.
127
200
  #
128
- def one_to_one(own_role, target_class, target_role)
129
- has_one_internal(own_role,target_class,target_role,:one)
130
- target_class.has_one_internal(target_role,self,own_role,:one)
201
+ def one_to_one(target_role, target_class, own_role, raw_props={}, &block)
202
+ props1 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
203
+ :name=>target_role, :upperBound=>1, :containment=>false}))
204
+ props2 = ReferenceDescription.new(self, _oppositeProps(raw_props).merge({
205
+ :name=>own_role, :upperBound=>1, :containment=>false}))
206
+ FeatureBlockEvaluator.eval(block, props1, props2)
207
+ _build_internal(props1, props2)
131
208
  end
132
209
 
133
- # Returns the names of the classes attributes pointing to a single object.
134
- # The result includes this kind of attributes of the superclass.
135
- def one_attributes
136
- @one_attributes ||= []
137
- result = @one_attributes.dup
138
- result += superclass.one_attributes if superclass.respond_to?(:one_attributes)
139
- result
210
+ def contains_one(target_role, target_class, own_role, raw_props={}, &block)
211
+ props1 = ReferenceDescription.new(target_class, _ownProps(raw_props).merge({
212
+ :name=>target_role, :upperBound=>1, :containment=>true}))
213
+ props2 = ReferenceDescription.new(self, _oppositeProps(raw_props).merge({
214
+ :name=>own_role, :upperBound=>1, :containment=>false}))
215
+ FeatureBlockEvaluator.eval(block, props1, props2)
216
+ _build_internal(props1, props2)
140
217
  end
141
-
142
- # Returns the names of the classes attributes pointing to many other objects
143
- # The result includes this kind of attributes of the superclass.
144
- def many_attributes
145
- @many_attributes ||= []
146
- result = @many_attributes.dup
147
- result += superclass.many_attributes if superclass.respond_to?(:many_attributes)
148
- result
218
+
219
+ def _metamodel_description # :nodoc:
220
+ @metamodel_description ||= []
149
221
  end
150
222
 
223
+ def inherited(c)
224
+ c._class_module
225
+ end
226
+
227
+ def _class_module # :nodoc:
228
+ unless const_defined?(:ClassModule)
229
+ const_set(:ClassModule, Module.new)
230
+ include const_get(:ClassModule)
231
+ end
232
+ const_get(:ClassModule)
233
+ end
234
+
151
235
  protected
152
-
153
- def has_one_internal(name, cls=nil, role=nil, kind=nil)
154
- @one_attributes ||= []
155
- return if @one_attributes.include?(name)
156
- @one_attributes << name
157
- BuildHelper.build self, binding, <<-CODE
158
- def #{name}=(val)
159
- return if val == @#{name}
160
- <% if cls %>
161
- raise _assignmentTypeError(self,val,#{cls}) unless val.nil? or val.is_a? #{cls}
162
- <% end %>
163
- oldval = @#{name}
164
- @#{name} = val
165
- _unregister(self,oldval,"#{role}","#{kind}")
166
- _register(self,val,"#{role}","#{kind}")
167
- end
168
- def #{name}
169
- @#{name}
236
+
237
+ # Central builder method
238
+ #
239
+ def _build_internal(props1, props2=nil)
240
+ _metamodel_description << props1
241
+ if props1.is_a?(ReferenceDescription) && props1.many?
242
+ _build_many_methods(props1, props2)
243
+ else
244
+ _build_one_methods(props1, props2)
245
+ end
246
+ if props2
247
+ # this is a bidirectional reference
248
+ props1.opposite, props2.opposite = props2, props1
249
+ other_class = props1.impl_type
250
+ other_class._metamodel_description << props2
251
+ raise "Internal error: second description must be a ReferenceDescription" \
252
+ unless props2.is_a?(ReferenceDescription)
253
+ if props2.many?
254
+ other_class._build_many_methods(props2, props1)
255
+ else
256
+ other_class._build_one_methods(props2, props1)
170
257
  end
171
- alias get<%= firstToUpper(name) %> #{name}
172
- alias set<%= firstToUpper(name) %> #{name}=
173
- CODE
258
+ end
174
259
  end
175
260
 
176
- def has_many_internal(name, cls=nil, role=nil, kind = nil)
177
- @many_attributes ||= []
178
- return if @many_attributes.include?(name)
179
- @many_attributes << name
180
- BuildHelper.build self, binding, <<-CODE
181
- def add<%= firstToUpper(name) %>(val)
182
- @#{name} = [] unless @#{name}
183
- return if val.nil? or @#{name}.include?(val)
184
- <% if cls %>
185
- raise _assignmentTypeError(self,val,#{cls}) unless val.nil? or val.is_a? #{cls}
186
- <% end %>
187
- @#{name}.push val
188
- _register(self, val, "#{role}", "#{kind}")
189
- end
190
- def remove<%= firstToUpper(name) %>(val)
191
- @#{name} = [] unless @#{name}
192
- return unless @#{name}.include?(val)
193
- @#{name}.delete val
194
- _unregister(self, val, "#{role}", "#{kind}")
195
- end
261
+ # To-One association methods
262
+ #
263
+ def _build_one_methods(props, other_props=nil)
264
+ name = props.value(:name)
265
+ other_role = other_props && other_props.value(:name)
266
+ other_kind = other_props && ( other_props.many? ? :many : :one )
267
+
268
+ if props.value(:derived)
269
+ build_derived_method(name, props, :one)
270
+ else
271
+ BuildHelper.build _class_module, binding, <<-CODE
272
+
273
+ def #{name}
274
+ <% if props.is_a?(AttributeDescription) && props.value(:defaultValueLiteral) %>
275
+ <% defVal = props.value(:defaultValueLiteral) %>
276
+ <% defVal = '"'+defVal+'"' if props.impl_type == String %>
277
+ <% defVal = ':'+defVal if props.impl_type.is_a?(DataTypes::Enum) %>
278
+ @#{name}.nil? ? <%= defVal %> : @#{name}
279
+ <% else %>
280
+ @#{name}
281
+ <% end %>
282
+ end
283
+ alias get<%= firstToUpper(name) %> #{name}
284
+
285
+ CODE
286
+ end
287
+
288
+ if props.value(:changeable)
289
+ BuildHelper.build _class_module, binding, <<-CODE
290
+
291
+ def #{name}=(val)
292
+ return if val == @#{name}
293
+ <%= type_check_code("val", props) %>
294
+ oldval = @#{name}
295
+ @#{name} = val
296
+ <% if other_role && other_kind %>
297
+ _unregister(self,oldval,"#{other_role}","#{other_kind}")
298
+ _register(self,val,"#{other_role}","#{other_kind}")
299
+ <% end %>
300
+ end
301
+ alias set<%= firstToUpper(name) %> #{name}=
302
+
303
+ CODE
304
+
305
+ end
306
+ end
307
+
308
+ # To-Many association methods
309
+ #
310
+ def _build_many_methods(props, other_props=nil)
311
+ name = props.value(:name)
312
+ other_role = other_props && other_props.value(:name)
313
+ other_kind = other_props && ( other_props.many? ? :many : :one )
314
+
315
+ if props.value(:derived)
316
+ build_derived_method(name, props, :many)
317
+ else
318
+ BuildHelper.build _class_module, binding, <<-CODE
319
+
320
+ def #{name}
321
+ ( @#{name} ? @#{name}.dup : [] )
322
+ end
323
+ alias get<%= firstToUpper(name) %> #{name}
324
+
325
+ CODE
326
+ end
327
+
328
+ if props.value(:changeable)
329
+ BuildHelper.build _class_module, binding, <<-CODE
330
+
331
+ def add<%= firstToUpper(name) %>(val)
332
+ @#{name} = [] unless @#{name}
333
+ return if val.nil? or @#{name}.include?(val)
334
+ <%= type_check_code("val", props) %>
335
+ @#{name}.push val
336
+ <% if other_role && other_kind %>
337
+ _register(self, val, "#{other_role}", "#{other_kind}")
338
+ <% end %>
339
+ end
340
+
341
+ def remove<%= firstToUpper(name) %>(val)
342
+ @#{name} = [] unless @#{name}
343
+ return unless @#{name}.include?(val)
344
+ @#{name}.delete val
345
+ <% if other_role && other_kind %>
346
+ _unregister(self, val, "#{other_role}", "#{other_kind}")
347
+ <% end %>
348
+ end
349
+
350
+ def #{name}=(val)
351
+ return if val.nil?
352
+ raise _assignmentTypeError(self, val, Array) unless val.is_a? Array
353
+ getGeneric(:#{name}).each {|e|
354
+ remove<%= firstToUpper(name) %>(e)
355
+ }
356
+ val.each {|v|
357
+ add<%= firstToUpper(name) %>(v)
358
+ }
359
+ end
360
+ alias set<%= firstToUpper(name) %> #{name}=
361
+
362
+ CODE
363
+ end
364
+
365
+ end
366
+
367
+ private
368
+
369
+ def build_derived_method(name, props, kind)
370
+ raise "Implement method #{name}_derived instead of method #{name}" \
371
+ if (public_instance_methods+protected_instance_methods+private_instance_methods).include?(name)
372
+ BuildHelper.build _class_module, binding, <<-CODE
373
+
196
374
  def #{name}
197
- ( @#{name} ? @#{name}.dup : [] )
375
+ raise "Derived feature requires public implementation of method #{name}_derived" \
376
+ unless respond_to?(:#{name+"_derived"})
377
+ val = #{name}_derived
378
+ <% if kind == :many %>
379
+ raise _assignmentTypeError(self,val,Array) unless val && val.is_a?(Array)
380
+ val.each do |v|
381
+ <%= type_check_code("v", props) %>
382
+ end
383
+ <% else %>
384
+ <%= type_check_code("val", props) %>
385
+ <% end %>
386
+ val
198
387
  end
199
- def #{name}=(val)
200
- return if val.nil?
201
- raise _assignmentTypeError(self, val, Array) unless val.is_a? Array
202
- #{name}.each {|e|
203
- remove<%= firstToUpper(name) %>(e)
204
- }
205
- val.each {|v|
206
- add<%= firstToUpper(name) %>(v)
207
- }
208
- end
209
- alias get<%= firstToUpper(name) %> #{name}
210
- alias set<%= firstToUpper(name) %> #{name}=
388
+ alias get#{firstToUpper(name)} #{name}
389
+ #TODO final_method :#{name}
390
+
211
391
  CODE
212
- end
392
+ end
393
+
394
+ private
395
+
396
+ def _ownProps(props)
397
+ Hash[*(props.select{|k,v| !(k.to_s =~ /^opposite_/)}.flatten)]
398
+ end
213
399
 
400
+ def _oppositeProps(props)
401
+ r = {}
402
+ props.each_pair do |k,v|
403
+ if k.to_s =~ /^opposite_(.*)$/
404
+ r[$1.to_sym] = v
405
+ end
406
+ end
407
+ r
408
+ end
409
+
214
410
  end
411
+
215
412
  end
216
413
 
217
414
  end