rgen 0.3.0 → 0.4.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 (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
@@ -13,6 +13,11 @@ module MetamodelBuilder
13
13
  module BuilderRuntime
14
14
  include NameHelper
15
15
 
16
+ def is_a?(c)
17
+ return super unless c.respond_to?(:_class_module)
18
+ kind_of?(c._class_module)
19
+ end
20
+
16
21
  def addGeneric(role, value)
17
22
  send("add#{firstToUpper(role)}",value)
18
23
  end
@@ -56,7 +61,8 @@ module BuilderRuntime
56
61
  end
57
62
  valueId = value.class.name
58
63
  valueId += "(" + value.name + ")" if value.respond_to?(:name) and value.name
59
- text += "Can not put a #{valueId} where a #{expected} is expected"
64
+ valueId += "(:" + value.to_s + ")" if value.is_a?(Symbol)
65
+ text += "Can not use a #{valueId} where a #{expected} is expected"
60
66
  StandardError.new(text)
61
67
  end
62
68
 
@@ -0,0 +1,67 @@
1
+ module RGen
2
+
3
+ module MetamodelBuilder
4
+
5
+ module DataTypes
6
+
7
+ # An enum object is used to describe possible attribute values within a
8
+ # MetamodelBuilder attribute definition. An attribute defined this way can only
9
+ # take the values specified when creating the Enum object.
10
+ # Literal values can only be symbols or true or false.
11
+ # Optionally a name may be specified for the enum object.
12
+ #
13
+ # Examples:
14
+ #
15
+ # Enum.new(:name => "AnimalEnum", :literals => [:cat, :dog])
16
+ # Enum.new(:literals => [:cat, :dog])
17
+ # Enum.new([:cat, :dog])
18
+ #
19
+ class Enum
20
+ attr_reader :name, :literals
21
+
22
+ # Creates a new named enum type object consisting of the elements passed as arguments.
23
+ def initialize(params)
24
+ if params.is_a?(Array)
25
+ @literals = params
26
+ @name = "anonymous"
27
+ elsif params.is_a?(Hash)
28
+ raise StandardError.new("Hash entry :literals is missing") unless params[:literals]
29
+ @literals = params[:literals]
30
+ @name = params[:name] || "anonymous"
31
+ else
32
+ raise StandardError.new("Pass an Array or a Hash")
33
+ end
34
+ end
35
+
36
+ # This method can be used to check if an object can be used as value for
37
+ # variables having this enum object as type.
38
+ def validLiteral?(l)
39
+ literals.include?(l)
40
+ end
41
+
42
+ def literals_as_strings
43
+ literals.collect do |l|
44
+ if l.is_a?(Symbol)
45
+ ":"+l.to_s
46
+ elsif l.is_a?(TrueClass) || l.is_a?(FalseClass)
47
+ l.to_s
48
+ else
49
+ raise StandardError.new("Literal values can only be symbols or true/false")
50
+ end
51
+ end
52
+ end
53
+
54
+ def to_s # :nodoc:
55
+ name
56
+ end
57
+ end
58
+
59
+ # Boolean is a predefined enum object having Ruby's true and false singletons
60
+ # as possible values.
61
+ Boolean = Enum.new(:name => "Boolean", :literals => [true, false])
62
+
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,30 @@
1
+ module RGen
2
+
3
+ module MetamodelBuilder
4
+
5
+ module Intermediate
6
+
7
+ class Annotation
8
+ attr_reader :details, :source
9
+
10
+ def initialize(hash)
11
+ if hash[:source] || hash[:details]
12
+ restKeys = hash.keys - [:source, :details]
13
+ raise "Hash key #{restKeys.first} not allowed." unless restKeys.empty?
14
+ raise "Details not provided, key :details is missing" unless hash[:details]
15
+ raise "Details must be provided as a hash" unless hash[:details].is_a?(Hash)
16
+ @details = hash[:details]
17
+ @source = hash[:source]
18
+ else
19
+ raise "Details must be provided as a hash" unless hash.is_a?(Hash)
20
+ @details = hash
21
+ end
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,232 @@
1
+ require 'rgen/metamodel_builder'
2
+
3
+ module RGen
4
+
5
+ module MetamodelBuilder
6
+
7
+ class MetamodelDescription
8
+
9
+ attr_reader :etype, :impl_type
10
+
11
+ def self.default_value(prop)
12
+ checkProperty(prop)
13
+ defaultValues[prop]
14
+ end
15
+
16
+ def self.has_default?(prop)
17
+ checkProperty(prop)
18
+ defaultValues.has_key?(prop)
19
+ end
20
+
21
+ def initialize(props)
22
+ @props = props.dup
23
+ end
24
+
25
+ def value(prop)
26
+ self.class.checkProperty(prop)
27
+ @props[prop]
28
+ end
29
+
30
+ def annotations
31
+ @annotations ||= []
32
+ end
33
+
34
+ def many?
35
+ value(:upperBound) > 1 || value(:upperBound) == -1
36
+ end
37
+
38
+ protected
39
+
40
+ def setupDefaults
41
+ self.class.propertySet.each do |p|
42
+ @props[p] = self.class.default_value(p) unless @props.has_key?(p)
43
+ end
44
+ end
45
+
46
+ def checkAllPropertiesSet
47
+ self.class.propertySet.each do |p|
48
+ raise StandardError.new("'#{p}' property not set") if !self.class.optionalProperties.include?(p) && @props[p].nil?
49
+ end
50
+ end
51
+
52
+ def checkForInvalidProperties
53
+ @props.keys.each do |p|
54
+ raise StandardError.new("invalid property #{p}") unless self.class.propertySet.include?(p)
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def descendent?(clazz1, clazz2)
61
+ return true if clazz1 == clazz2 || clazz1.superclass == clazz2
62
+ return false if clazz1.superclass.nil?
63
+ descendent?(clazz1.superclass, clazz2)
64
+ end
65
+
66
+ def self.checkProperty(prop)
67
+ raise ArgumentError.new("Not a valid property: #{prop}") unless propertySet.include?(prop)
68
+ end
69
+
70
+ def to_s
71
+ self.class.to_s + ": " +
72
+ self.class.propertySet.collect{|p| "#{p}=>#{value(p)}"}.join(", ")
73
+ end
74
+
75
+ def self.propertySet
76
+ [ :name ]
77
+ end
78
+
79
+
80
+ def self.optionalProperties
81
+ []
82
+ end
83
+
84
+ def self.defaultValues
85
+ { }
86
+ end
87
+
88
+ def self.typeMap
89
+ { :EString => String,
90
+ :EInt => Integer,
91
+ :EFloat => Float,
92
+ :EBoolean => RGen::MetamodelBuilder::DataTypes::Boolean,
93
+ :EJavaObject => Object,
94
+ :ERubyObject => Object,
95
+ :EJavaClass => Class,
96
+ :ERubyClass => Class }
97
+ end
98
+
99
+ end
100
+
101
+ # DERIVED: ordered = true, unique = false, lowerBound = 0/1, upperBound = 1
102
+ # DERIVED: when :derived : changeable= false, :volatile=true, transient=true
103
+ class AttributeDescription < MetamodelDescription
104
+
105
+ def initialize(type, props)
106
+ super(props)
107
+ # type default
108
+ type ||= :EString
109
+ setupType(type)
110
+ # fixed values can not be changed by user
111
+ setupDefaults
112
+ checkForInvalidProperties
113
+ if @props[:derived]
114
+ @props[:changeable] = false
115
+ @props[:volatile] = true
116
+ @props[:transient] = true
117
+ end
118
+ checkAllPropertiesSet
119
+ end
120
+
121
+ private
122
+
123
+ def setupType(type)
124
+ if self.class.typeMap.keys.include?(type)
125
+ @etype = type
126
+ @impl_type = self.class.typeMap[type]
127
+ elsif self.class.typeMap.invert.keys.include?(type)
128
+ @etype = self.class.typeMap.invert[type]
129
+ @impl_type = type
130
+ elsif type.is_a?(RGen::MetamodelBuilder::DataTypes::Enum)
131
+ @etype = :EEnumerable
132
+ @impl_type = type
133
+ else
134
+ raise ArgumentError.new("Type invalid: " + type.to_s)
135
+ end
136
+ end
137
+
138
+ def self.propertySet
139
+ super | [
140
+ :ordered,
141
+ :unique,
142
+ :changeable,
143
+ :volatile,
144
+ :transient,
145
+ :unsettable,
146
+ :derived,
147
+ :lowerBound,
148
+ :upperBound,
149
+ :defaultValueLiteral ]
150
+ end
151
+
152
+ def self.optionalProperties
153
+ super | [
154
+ :defaultValueLiteral
155
+ ]
156
+ end
157
+
158
+ def self.defaultValues
159
+ super.merge(
160
+ { :ordered => true,
161
+ :unique => true,
162
+ :changeable => true,
163
+ :volatile => false,
164
+ :transient => false,
165
+ :unsettable => false,
166
+ :derived => false,
167
+ :lowerBound => 0 })
168
+ end
169
+
170
+ end
171
+
172
+ # DERIVED default: lowerBound => 0/1 (required?), upperBound => 1/-1 (many?), containment (contains_xxx?),
173
+ # DERIVED: when :derived : changeable= false, :volatile=true, transient=true
174
+ class ReferenceDescription < MetamodelDescription
175
+ attr_accessor :opposite
176
+
177
+ def initialize(type, props)
178
+ super(props)
179
+ setupType(type)
180
+ setupDefaults
181
+ checkForInvalidProperties
182
+ if @props[:derived]
183
+ @props[:changeable] = false
184
+ @props[:volatile] = true
185
+ @props[:transient] = true
186
+ end
187
+ checkAllPropertiesSet
188
+ end
189
+
190
+ private
191
+
192
+ def setupType(type)
193
+ if type.is_a?(Class) && descendent?(type, RGen::MetamodelBuilder::MMBase)
194
+ @etype = nil
195
+ @impl_type = type
196
+ else
197
+ raise ArgumentError.new("Type is not a MMBase: " + type.to_s)
198
+ end
199
+ end
200
+
201
+ def self.propertySet
202
+ super | [
203
+ :ordered,
204
+ :unique,
205
+ :changeable,
206
+ :volatile,
207
+ :transient,
208
+ :unsettable,
209
+ :derived,
210
+ :lowerBound,
211
+ :upperBound,
212
+ :resolveProxies,
213
+ :containment ]
214
+ end
215
+
216
+ def self.defaultValues
217
+ super.merge({
218
+ :ordered => true,
219
+ :unique => true,
220
+ :changeable => true,
221
+ :volatile => false,
222
+ :transient => false,
223
+ :unsettable => false,
224
+ :derived => false,
225
+ :lowerBound => 0,
226
+ :resolveProxies => true })
227
+ end
228
+ end
229
+
230
+ end
231
+
232
+ end
@@ -0,0 +1,23 @@
1
+
2
+ module RGen
3
+
4
+ module MetamodelBuilder
5
+
6
+ def self.MMMultiple(*superclasses)
7
+ c = Class.new(MMBase)
8
+ class << c
9
+ attr_reader :multiple_superclasses
10
+ end
11
+ c.instance_variable_set(:@multiple_superclasses, superclasses)
12
+ superclasses.collect{|sc| sc.ancestors}.flatten.
13
+ reject{|m| m.is_a?(Class)}.each do |arg|
14
+ c.instance_eval do
15
+ include arg
16
+ end
17
+ end
18
+ return c
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,33 @@
1
+ require 'rgen/ecore/ecore_instantiator'
2
+ require 'rgen/metamodel_builder/intermediate/annotation'
3
+
4
+ module RGen
5
+
6
+ module MetamodelBuilder
7
+
8
+ # This module is used to extend modules which should be
9
+ # part of RGen metamodels
10
+ module ModuleExtension
11
+ include RGen::ECore::ECoreInstantiator
12
+
13
+ def annotation(hash)
14
+ _annotations << Intermediate::Annotation.new(hash)
15
+ end
16
+
17
+ def _annotations
18
+ @_annotations ||= []
19
+ end
20
+
21
+ def final_method(m)
22
+ @final_methods ||= []
23
+ @final_methods << m
24
+ end
25
+
26
+ def method_added(m)
27
+ raise "Method #{m} can not be redefined" if @final_methods && @final_methods.include?(m)
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,56 @@
1
+ require 'rgen/ecore/ecore'
2
+
3
+ module RGen
4
+
5
+ module ModelComparator
6
+
7
+ # This method compares to models regarding equality
8
+ # For this the identity of a model element is defined based on identity
9
+ # of all attributes and referenced elements.
10
+ # Arrays are sorted before comparison if possible (if <=> is provided).
11
+ #
12
+ def modelEqual?(a, b, featureIgnoreList=[])
13
+ @modelEqual_visited = {}
14
+ _modelEqual_internal(a, b, featureIgnoreList, [])
15
+ end
16
+
17
+ def _modelEqual_internal(a, b, featureIgnoreList, path)
18
+ return true if @modelEqual_visited[[a,b]]
19
+ @modelEqual_visited[[a,b]] = true
20
+ return true if a.nil? && b.nil?
21
+ unless a.class == b.class
22
+ puts "#{path.inspect}\n Classes differ: #{a} vs. #{b}"
23
+ return false
24
+ end
25
+ if a.is_a?(Array)
26
+ unless a.size == b.size
27
+ puts "#{path.inspect}\n Array size differs: #{a.size} vs. #{b.size}"
28
+ return false
29
+ end
30
+ as = a
31
+ as = a.sort if a.all?{|o| o.respond_to?('<=>')}
32
+ bs = b
33
+ bs = b.sort if b.all?{|o| o.respond_to?('<=>')}
34
+ a.each_index do |i|
35
+ return false unless _modelEqual_internal(as[i], bs[i], featureIgnoreList, path+[i])
36
+ end
37
+ else
38
+ a.class.ecore.eAllStructuralFeatures.reject{|f| f.derived}.each do |feat|
39
+ next if featureIgnoreList.include?(feat.name)
40
+ if feat.eType.is_a?(RGen::ECore::EDataType)
41
+ unless a.getGeneric(feat.name) == b.getGeneric(feat.name)
42
+ puts "#{path.inspect}\n Value '#{feat.name}' differs: #{a.getGeneric(feat.name)} vs. #{b.getGeneric(feat.name)}"
43
+ return false
44
+ end
45
+ else
46
+ return false unless _modelEqual_internal(a.getGeneric(feat.name), b.getGeneric(feat.name), featureIgnoreList, path+["#{a.respond_to?(:name) && a.name}:#{feat.name}"])
47
+ end
48
+ end
49
+ end
50
+ return true
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+