rgen 0.4.6 → 0.5.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 (60) hide show
  1. data/CHANGELOG +95 -83
  2. data/Rakefile +4 -3
  3. data/lib/ea_support/ea_support.rb +54 -0
  4. data/lib/ea_support/id_store.rb +32 -0
  5. data/lib/ea_support/uml13_ea_metamodel.rb +562 -0
  6. data/lib/ea_support/uml13_ea_metamodel_ext.rb +45 -0
  7. data/lib/ea_support/uml13_ea_metamodel_generator.rb +43 -0
  8. data/lib/ea_support/uml13_ea_to_uml13.rb +72 -0
  9. data/lib/ea_support/uml13_to_uml13_ea.rb +82 -0
  10. data/lib/rgen/ecore/ecore.rb +16 -2
  11. data/lib/rgen/ecore/ecore_builder_methods.rb +81 -0
  12. data/lib/rgen/ecore/ecore_instantiator.rb +5 -1
  13. data/lib/rgen/metamodel_builder/builder_extensions.rb +11 -3
  14. data/lib/rgen/metamodel_builder/module_extension2.rb +205 -0
  15. data/lib/rgen/method_delegation.rb +99 -0
  16. data/lib/rgen/model_builder.rb +27 -0
  17. data/lib/rgen/model_builder/builder_context.rb +318 -0
  18. data/lib/rgen/model_builder/model_serializer.rb +201 -0
  19. data/lib/rgen/model_builder/reference_resolver.rb +156 -0
  20. data/lib/rgen/template_language/directory_template_container.rb +6 -2
  21. data/lib/rgen/template_language/output_handler.rb +2 -4
  22. data/lib/rgen/template_language/template_container.rb +212 -195
  23. data/lib/rgen/transformer.rb +95 -4
  24. data/lib/transformers/ecore_to_uml13.rb +66 -0
  25. data/lib/transformers/uml13_to_ecore.rb +16 -7
  26. data/test/ea_instantiator_test.rb +8 -14
  27. data/test/ea_serializer_test.rb +3 -9
  28. data/test/ea_serializer_test/ea_testmodel_regenerated.xml +2 -2
  29. data/test/ea_serializer_test/ea_testmodel_regenerated_import.log +3 -0
  30. data/test/metamodel_roundtrip_test/TestModel_Regenerated.rb +19 -19
  31. data/test/metamodel_roundtrip_test/houseMetamodel_Regenerated.ecore +44 -44
  32. data/test/method_delegation_test.rb +178 -0
  33. data/test/model_builder/builder_context_test.rb +59 -0
  34. data/test/model_builder/builder_test.rb +284 -0
  35. data/test/model_builder/ecore_internal.rb +103 -0
  36. data/test/model_builder/ecore_original.rb +163 -0
  37. data/test/model_builder/ecore_original_regenerated.rb +163 -0
  38. data/test/model_builder/reference_resolver_test.rb +156 -0
  39. data/test/model_builder/serializer_test.rb +63 -0
  40. data/test/model_builder_test.rb +4 -0
  41. data/test/rgen_test.rb +2 -0
  42. data/test/template_language_test.rb +41 -1
  43. data/test/template_language_test/expected_result1.txt +1 -3
  44. data/test/template_language_test/templates/define_local_test/local.tpl +8 -0
  45. data/test/template_language_test/templates/define_local_test/test.tpl +8 -0
  46. data/test/template_language_test/templates/evaluate_test/test.tpl +7 -0
  47. data/test/template_language_test/templates/no_indent_test/no_indent.tpl +3 -0
  48. data/test/template_language_test/templates/no_indent_test/sub1/no_indent.tpl +3 -0
  49. data/test/template_language_test/templates/no_indent_test/test.tpl +24 -0
  50. data/test/template_language_test/templates/no_indent_test/test2.tpl +13 -0
  51. data/test/template_language_test/templates/no_indent_test/test3.tpl +10 -0
  52. data/test/template_language_test/templates/template_resolution_test/sub1.tpl +9 -0
  53. data/test/template_language_test/templates/template_resolution_test/sub1/sub1.tpl +3 -0
  54. data/test/template_language_test/templates/template_resolution_test/test.tpl +4 -0
  55. data/test/template_language_test/testout.txt +1 -3
  56. data/test/testmodel/ea_testmodel_import.log +1 -0
  57. data/test/testmodel/ea_testmodel_regenerated.xml +808 -0
  58. data/test/transformer_test.rb +3 -5
  59. metadata +52 -3
  60. data/lib/instantiators/ea_instantiator.rb +0 -39
@@ -0,0 +1,99 @@
1
+ module RGen
2
+
3
+ module MethodDelegation
4
+
5
+ class << self
6
+
7
+ def registerDelegate(delegate, object, method)
8
+ method = method.to_sym
9
+ createDelegateStore(object)
10
+ if object._methodDelegates[method]
11
+ object._methodDelegates[method] << delegate
12
+ else
13
+ object._methodDelegates[method] = [delegate]
14
+ createDelegatingMethod(object, method)
15
+ end
16
+ end
17
+
18
+ def unregisterDelegate(delegate, object, method)
19
+ method = method.to_sym
20
+ return unless object.respond_to?(:_methodDelegates)
21
+ return unless object._methodDelegates[method]
22
+ object._methodDelegates[method].delete(delegate)
23
+ if object._methodDelegates[method].empty?
24
+ object._methodDelegates[method] = nil
25
+ removeDelegatingMethod(object, method)
26
+ removeDelegateStore(object)
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def createDelegateStore(object)
33
+ return if object.respond_to?(:_methodDelegates)
34
+ class << object
35
+ def _methodDelegates
36
+ @_methodDelegates ||= {}
37
+ end
38
+ end
39
+ end
40
+
41
+ def removeDelegateStore(object)
42
+ return unless object.respond_to?(:_methodDelegates)
43
+ class << object
44
+ remove_method(:_methodDelegates)
45
+ end
46
+ end
47
+
48
+ def createDelegatingMethod(object, method)
49
+ if object.methods.include?(method.to_s)
50
+ object.instance_eval <<-END
51
+ class << self
52
+ alias #{aliasMethodName(method)} #{method}
53
+ end
54
+ END
55
+ end
56
+
57
+ # define the delegating method
58
+ object.instance_eval <<-END
59
+ class << self
60
+ def #{method}(*args, &block)
61
+ @_methodDelegates[:#{method}].each do |d|
62
+ catch(:continue) do
63
+ return d.#{method}_delegated(self, *args, &block)
64
+ end
65
+ end
66
+ # if aliased method does not exist, we want an exception
67
+ #{aliasMethodName(method)}(*args, &block)
68
+ end
69
+ end
70
+ END
71
+ end
72
+
73
+ def removeDelegatingMethod(object, method)
74
+ if object.methods.include?(aliasMethodName(method))
75
+ # there is an aliased original, restore it
76
+ object.instance_eval <<-END
77
+ class << self
78
+ alias #{method} #{aliasMethodName(method)}
79
+ remove_method(:#{aliasMethodName(method)})
80
+ end
81
+ END
82
+ else
83
+ # just delete the delegating method
84
+ object.instance_eval <<-END
85
+ class << self
86
+ remove_method(:#{method})
87
+ end
88
+ END
89
+ end
90
+ end
91
+
92
+ def aliasMethodName(method)
93
+ "#{method}_delegate_original"
94
+ end
95
+ end
96
+
97
+ end
98
+
99
+ end
@@ -0,0 +1,27 @@
1
+ require 'rgen/model_builder/builder_context'
2
+ require 'rgen/method_delegation'
3
+ #require 'ruby-prof'
4
+
5
+ module RGen
6
+
7
+ module ModelBuilder
8
+
9
+ def self.build(package, env=nil, builderMethodsModule=nil, &block)
10
+ resolver = ReferenceResolver.new
11
+ bc = BuilderContext.new(package, builderMethodsModule, resolver, env)
12
+ contextModule = eval("Module.nesting", block.binding).first
13
+ MethodDelegation.registerDelegate(bc, contextModule, "const_missing")
14
+ #RubyProf.start
15
+ bc.instance_eval(&block)
16
+ #prof = RubyProf.stop
17
+ #File.open("profile_flat.txt","w+") do |f|
18
+ # RubyProf::FlatPrinter.new(prof).print(f, 0)
19
+ # end
20
+ MethodDelegation.unregisterDelegate(bc, contextModule, "const_missing")
21
+ #puts "Resolving..."
22
+ resolver.resolve(bc.toplevelElements)
23
+ bc.toplevelElements
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,318 @@
1
+ require 'rgen/ecore/ecore_ext'
2
+ require 'rgen/model_builder/reference_resolver'
3
+
4
+ module RGen
5
+
6
+ module ModelBuilder
7
+
8
+ class BuilderContext
9
+ attr_reader :toplevelElements
10
+
11
+ def initialize(package, extensionsModule, resolver, env=nil)
12
+ package = package.ecore unless package.is_a?(RGen::ECore::EPackage)
13
+ raise "First argument must be a metamodel package" \
14
+ unless package.is_a?(RGen::ECore::EPackage)
15
+ @rootPackage, @env = package, env
16
+ @commandResolver = CommandResolver.new(package, extensionsModule, self)
17
+ @package = @rootPackage
18
+ @resolver = resolver
19
+ @contextStack = []
20
+ @toplevelElements = []
21
+ @helperNames = {}
22
+ end
23
+
24
+ def const_missing_delegated(delegator, const)
25
+ ConstPathElement.new(const, self)
26
+ end
27
+
28
+ class CommandResolver
29
+ def initialize(rootPackage, extensionsModule, builderContext)
30
+ @extensionFactory = ExtensionContainerFactory.new(rootPackage, extensionsModule, builderContext)
31
+ @packageResolver = PackageResolver.new(rootPackage, @extensionFactory)
32
+ @resolveCommand = {}
33
+ end
34
+
35
+ def resolveCommand(cmd, parentPackage)
36
+ return @resolveCommand[[parentPackage, cmd]] if @resolveCommand.has_key?([parentPackage, cmd])
37
+ package = @packageResolver.packageByCommand(parentPackage, cmd)
38
+ result = nil
39
+ if package
40
+ extensionContainer = @extensionFactory.extensionContainer(package)
41
+ if extensionContainer.respond_to?(cmd)
42
+ result = extensionContainer
43
+ else
44
+ className = cmd.to_s[0..0].upcase + cmd.to_s[1..-1]
45
+ result = package.eClasses.find{|c| c.name == className}
46
+ end
47
+ end
48
+ @resolveCommand[[parentPackage, cmd]] = [package, result]
49
+ end
50
+ end
51
+
52
+ def method_missing(m, *args, &block)
53
+ package, classOrContainer = @commandResolver.resolveCommand(m, @package)
54
+ return super if package.nil?
55
+ return classOrContainer.send(m, *args, &block) if classOrContainer.is_a?(ExtensionContainerFactory::ExtensionContainer)
56
+ eClass = classOrContainer
57
+ nameArg, argHash = self.class.processArguments(args)
58
+ internalName = nameArg || argHash[:name]
59
+ argHash[:name] ||= nameArg if nameArg && self.class.hasNameAttribute(eClass)
60
+ resolverJobs, asRole, helperName = self.class.filterArgHash(argHash, eClass)
61
+ element = eClass.instanceClass.new(argHash)
62
+ @resolver.setElementName(element, internalName)
63
+ @env << element if @env
64
+ contextElement = @contextStack.last
65
+ if contextElement
66
+ self.class.associateWithContextElement(element, contextElement, asRole)
67
+ else
68
+ @toplevelElements << element
69
+ end
70
+ resolverJobs.each do |job|
71
+ job.receiver = element
72
+ job.namespace = contextElement
73
+ @resolver.addJob(job)
74
+ end
75
+ # process block
76
+ if block
77
+ @contextStack.push(element)
78
+ @package, oldPackage = package, @package
79
+ instance_eval(&block)
80
+ @package = oldPackage
81
+ @contextStack.pop
82
+ end
83
+ element
84
+ end
85
+
86
+ def _using(constPathElement, &block)
87
+ @package, oldPackage =
88
+ self.class.resolvePackage(@package, @rootPackage, constPathElement.constPath), @package
89
+ instance_eval(&block)
90
+ @package = oldPackage
91
+ end
92
+
93
+ def _context(depth=1)
94
+ @contextStack[-depth]
95
+ end
96
+
97
+ class ExtensionContainerFactory
98
+
99
+ class ExtensionContainer
100
+ def initialize(builderContext)
101
+ @builderContext = builderContext
102
+ end
103
+ def method_missing(m, *args, &block)
104
+ @builderContext.send(m, *args, &block)
105
+ end
106
+ end
107
+
108
+ def initialize(rootPackage, extensionsModule, builderContext)
109
+ @rootPackage, @extensionsModule, @builderContext = rootPackage, extensionsModule, builderContext
110
+ @extensionContainer = {}
111
+ end
112
+
113
+ def moduleForPackage(package)
114
+ qName = package.qualifiedName
115
+ rqName = @rootPackage.qualifiedName
116
+ raise "Package #{qName} is not contained within #{rqName}" unless qName.index(rqName) == 0
117
+ path = qName.sub(rqName,'').split('::')
118
+ path.shift if path.first == ""
119
+ mod = @extensionsModule
120
+ path.each do |p|
121
+ if mod && mod.const_defined?(p)
122
+ mod = mod.const_get(p)
123
+ else
124
+ mod = nil
125
+ break
126
+ end
127
+ end
128
+ mod
129
+ end
130
+
131
+ def extensionContainer(package)
132
+ return @extensionContainer[package] if @extensionContainer[package]
133
+ container = ExtensionContainer.new(@builderContext)
134
+ extensionModule = moduleForPackage(package)
135
+ container.extend(extensionModule) if extensionModule
136
+ @extensionContainer[package] = container
137
+ end
138
+ end
139
+
140
+ class PackageResolver
141
+ def initialize(rootPackage, extensionFactory)
142
+ @rootPackage = rootPackage
143
+ @extensionFactory = extensionFactory
144
+ @packageByCommand = {}
145
+ end
146
+
147
+ def packageByCommand(contextPackage, name)
148
+ return @packageByCommand[[contextPackage, name]] if @packageByCommand.has_key?([contextPackage, name])
149
+ if @extensionFactory.extensionContainer(contextPackage).respond_to?(name)
150
+ result = contextPackage
151
+ else
152
+ className = name.to_s[0..0].upcase + name.to_s[1..-1]
153
+ eClass = contextPackage.eClasses.find{|c| c.name == className}
154
+ if eClass
155
+ result = contextPackage
156
+ elsif contextPackage != @rootPackage
157
+ result = packageByCommand(contextPackage.eSuperPackage, name)
158
+ else
159
+ result = nil
160
+ end
161
+ end
162
+ @packageByCommand[[contextPackage, name]] = result
163
+ end
164
+ end
165
+
166
+ class ConstPathElement < Module
167
+ def initialize(name, builderContext, parent=nil)
168
+ @name = name.to_s
169
+ @builderContext = builderContext
170
+ @parent = parent
171
+ end
172
+
173
+ def const_missing(const)
174
+ ConstPathElement.new(const, @builderContext, self)
175
+ end
176
+
177
+ def method_missing(m, *args, &block)
178
+ @builderContext._using(self) do
179
+ send(m, *args, &block)
180
+ end
181
+ end
182
+
183
+ def constPath
184
+ if @parent
185
+ @parent.constPath << @name
186
+ else
187
+ [@name]
188
+ end
189
+ end
190
+ end
191
+
192
+ # helper methods put in the class object to be out of the way of
193
+ # method evaluation in the builder context
194
+ class << self
195
+ class PackageNotFoundException < Exception
196
+ end
197
+
198
+ def resolvePackage(contextPackage, rootPackage, path)
199
+ begin
200
+ return resolvePackageDownwards(contextPackage, path)
201
+ rescue PackageNotFoundException
202
+ if contextPackage.eSuperPackage && contextPackage != rootPackage
203
+ return resolvePackage(contextPackage.eSuperPackage, rootPackage, path)
204
+ else
205
+ raise
206
+ end
207
+ end
208
+ end
209
+
210
+ def resolvePackageDownwards(contextPackage, path)
211
+ first, *rest = path
212
+ package = contextPackage.eSubpackages.find{|p| p.name == first}
213
+ raise PackageNotFoundException.new("Could not resolve package: #{first} is not a subpackage of #{contextPackage.name}") unless package
214
+ if rest.empty?
215
+ package
216
+ else
217
+ resolvePackageDownwards(package, rest)
218
+ end
219
+ end
220
+
221
+ def processArguments(args)
222
+ unless (args.size == 2 && args.first.is_a?(String) && args.last.is_a?(Hash)) ||
223
+ (args.size == 1 && (args.first.is_a?(String) || args.first.is_a?(Hash))) ||
224
+ args.size == 0
225
+ raise "Provide a Hash to set feature values, " +
226
+ "optionally the first argument may be a String specifying " +
227
+ "the value of the \"name\" attribute."
228
+ end
229
+ if args.last.is_a?(Hash)
230
+ argHash = args.last
231
+ else
232
+ argHash = {}
233
+ end
234
+ nameArg = args.first if args.first.is_a?(String)
235
+ [nameArg, argHash]
236
+ end
237
+
238
+ def filterArgHash(argHash, eClass)
239
+ resolverJobs = []
240
+ asRole, helperName = nil, nil
241
+ refByName = {}
242
+ eAllReferences(eClass).each {|r| refByName[r.name] = r}
243
+ argHash.each_pair do |k,v|
244
+ if k == :as
245
+ asRole = v
246
+ argHash.delete(k)
247
+ elsif k == :name && !hasNameAttribute(eClass)
248
+ helperName = v
249
+ argHash.delete(k)
250
+ elsif v.is_a?(String)
251
+ ref = refByName[k.to_s]#eAllReferences(eClass).find{|r| r.name == k.to_s}
252
+ if ref
253
+ argHash.delete(k)
254
+ resolverJobs << ReferenceResolver::ResolverJob.new(nil, ref, nil, v)
255
+ end
256
+ elsif v.is_a?(Array)
257
+ ref = refByName[k.to_s] #eAllReferences(eClass).find{|r| r.name == k.to_s}
258
+ ref && v.dup.each do |e|
259
+ if e.is_a?(String)
260
+ v.delete(e)
261
+ resolverJobs << ReferenceResolver::ResolverJob.new(nil, ref, nil, e)
262
+ end
263
+ end
264
+ end
265
+ end
266
+ [ resolverJobs, asRole, helperName ]
267
+ end
268
+
269
+ def hasNameAttribute(eClass)
270
+ @hasNameAttribute ||= {}
271
+ @hasNameAttribute[eClass] ||= eClass.eAllAttributes.any?{|a| a.name == "name"}
272
+ end
273
+
274
+ def eAllReferences(eClass)
275
+ @eAllReferences ||= {}
276
+ @eAllReferences[eClass] ||= eClass.eAllReferences
277
+ end
278
+
279
+ def containmentRefs(contextClass, eClass)
280
+ @containmentRefs ||= {}
281
+ @containmentRefs[[contextClass, eClass]] ||=
282
+ eAllReferences(contextClass).select do |r|
283
+ r.containment && (eClass.eAllSuperTypes << eClass).include?(r.eType)
284
+ end
285
+ end
286
+
287
+ def associateWithContextElement(element, contextElement, asRole)
288
+ return unless contextElement
289
+ contextClass = contextElement.class.ecore
290
+ if asRole
291
+ asRoleRef = eAllReferences(contextClass).find{|r| r.name == asRole.to_s}
292
+ raise "Context class #{contextClass.name} has no reference named #{asRole}" unless asRoleRef
293
+ ref = asRoleRef
294
+ else
295
+ possibleContainmentRefs = containmentRefs(contextClass, element.class.ecore)
296
+ if possibleContainmentRefs.size == 1
297
+ ref = possibleContainmentRefs.first
298
+ elsif possibleContainmentRefs.size == 0
299
+ raise "Context class #{contextClass.name} can not contain a #{element.class.ecore.name}"
300
+ else
301
+ raise "Context class #{contextClass.name} has several containment references to a #{element.class.ecore.name}." +
302
+ " Clearify using \":as => <role>\""
303
+ end
304
+ end
305
+ if ref.many
306
+ contextElement.addGeneric(ref.name, element)
307
+ else
308
+ contextElement.setGeneric(ref.name, element)
309
+ end
310
+ end
311
+
312
+ end
313
+
314
+ end
315
+
316
+ end
317
+
318
+ end
@@ -0,0 +1,201 @@
1
+ require 'rgen/array_extensions'
2
+ require 'rgen/ecore/ecore_ext'
3
+
4
+ module RGen
5
+
6
+ module ModelBuilder
7
+
8
+ class ModelSerializer
9
+
10
+ def initialize(writable, rootPackage)
11
+ @writable = writable
12
+ @currentPackage = rootPackage
13
+ @qualifiedElementName = {}
14
+ @internalElementName = {}
15
+ @relativeQualifiedElementName = {}
16
+ end
17
+
18
+ def serialize(elements)
19
+ calcQualifiedElementNames(elements)
20
+ unifyQualifiedElementNames
21
+ elements = [elements] unless elements.is_a?(Enumerable)
22
+ elements.each do |e|
23
+ serializeElement(e)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def serializeElement(element, viaRef=nil, namePath=[], indent=0)
30
+ className = element.class.ecore.name
31
+ cmd = className[0..0].downcase+className[1..-1]
32
+ args = ["\"#{@internalElementName[element]}\""]
33
+ namePath = namePath + [@internalElementName[element]]
34
+ childs = {}
35
+ eAllStructuralFeatures(element).each do |f|
36
+ next if f.derived
37
+ if f.is_a?(RGen::ECore::EAttribute)
38
+ next if f.name == "name" && element.name == @internalElementName[element]
39
+ val = element.getGeneric(f.name)
40
+ #puts f.defaultValue.inspect if f.name == "isRoot"
41
+ args << ":#{f.name} => #{serializeAttribute(val)}" unless val == f.defaultValue || val.nil?
42
+ elsif !f.containment
43
+ next if f.eOpposite && f.eOpposite == viaRef
44
+ val = element.getGeneric(f.name)
45
+ refString = serializeReference(element, f, val)
46
+ args << ":#{f.name} => #{refString}" if refString
47
+ else
48
+ cs = element.getGeneric(f.name)
49
+ refString = nil
50
+ if cs.is_a?(Array)
51
+ cs.compact!
52
+ rcs = cs.select{|c| serializeChild?(c, namePath)}
53
+ childs[f] = rcs unless rcs.empty?
54
+ refString = serializeReference(element, f, cs-rcs)
55
+ else
56
+ if cs && serializeChild?(cs, namePath)
57
+ childs[f] = [cs]
58
+ else
59
+ refString = serializeReference(element, f, cs)
60
+ end
61
+ end
62
+ args << ":#{f.name} => #{refString}" if refString
63
+ end
64
+ end
65
+ cmd = elementPackage(element)+"."+cmd if elementPackage(element).size > 0
66
+ @writable.write " " * indent + cmd + " " + args.join(", ")
67
+ if childs.size > 0
68
+ @writable.write " do\n"
69
+ oldPackage, @currentPackage = @currentPackage, element.class.ecore.ePackage
70
+ childs.each_pair do |f,cs|
71
+ cs.each {|c| serializeElement(c, f, namePath, indent+1) }
72
+ end
73
+ @currentPackage = oldPackage
74
+ @writable.write " " * indent + "end\n"
75
+ else
76
+ @writable.write "\n"
77
+ end
78
+ end
79
+
80
+ def serializeChild?(child, namePath)
81
+ @qualifiedElementName[child][0..-2] == namePath
82
+ end
83
+
84
+ def serializeAttribute(value)
85
+ if value.is_a?(String)
86
+ "\"#{value.gsub("\"","\\\"")}\""
87
+ elsif value.is_a?(Symbol)
88
+ ":#{value}"
89
+ elsif value.nil?
90
+ "nil"
91
+ else
92
+ value.to_s
93
+ end
94
+ end
95
+
96
+ def serializeReference(element, ref, value)
97
+ if value.is_a?(Array)
98
+ value = value.compact
99
+ value = value.select{|v| compareWithOppositeReference(element, v) > 0} if ref.eOpposite
100
+ qualNames = value.collect do |v|
101
+ relativeQualifiedElementName(v, element).join(".")
102
+ end
103
+ !qualNames.empty? && ("[" + qualNames.collect { |v| "\"#{v}\"" }.join(", ") + "]")
104
+ elsif value && (!ref.eOpposite || compareWithOppositeReference(element, value) > 0)
105
+ qualName = relativeQualifiedElementName(value, element).join(".")
106
+ ("\"#{qualName}\"")
107
+ end
108
+ end
109
+
110
+ def compareWithOppositeReference(element, target)
111
+ result = relativeQualifiedElementName(element, target).size <=>
112
+ relativeQualifiedElementName(target, element).size
113
+ return result if result != 0
114
+ result = element.class.name <=> target.class.name
115
+ return result if result != 0
116
+ element.object_id <=> target.object_id
117
+ end
118
+
119
+ def elementPackage(element)
120
+ @elementPackage ||= {}
121
+ return @elementPackage[element] if @elementPackage[element]
122
+ eNames = element.class.ecore.ePackage.qualifiedName.split("::")
123
+ rNames = @currentPackage.qualifiedName.split("::")
124
+ while eNames.first == rNames.first && !eNames.first.nil?
125
+ eNames.shift
126
+ rNames.shift
127
+ end
128
+ @elementPackage[element] = eNames.join("::")
129
+ end
130
+
131
+ def relativeQualifiedElementName(element, context)
132
+ return @relativeQualifiedElementName[[element, context]] if @relativeQualifiedElementName[[element, context]]
133
+ # elements which are not in the @qualifiedElementName Hash are not in the scope
134
+ # of this serialization and will be ignored
135
+ return [] if element.nil? || @qualifiedElementName[element].nil?
136
+ return [] if context.nil? || @qualifiedElementName[context].nil?
137
+ eNames = @qualifiedElementName[element].dup
138
+ cNames = @qualifiedElementName[context].dup
139
+ while eNames.first == cNames.first && eNames.size > 1
140
+ eNames.shift
141
+ cNames.shift
142
+ end
143
+ @relativeQualifiedElementName[[element, context]] = eNames
144
+ end
145
+
146
+ def calcQualifiedElementNames(elements, prefix=[], takenNames=[])
147
+ elements = [elements] unless elements.is_a?(Array)
148
+ elements.compact!
149
+ elements.each do |element|
150
+ qualifiedNamePath = prefix + [calcInternalElementName(element, takenNames)]
151
+ @qualifiedElementName[element] ||= []
152
+ @qualifiedElementName[element] << qualifiedNamePath
153
+ takenChildNames = []
154
+ eAllStructuralFeatures(element).each do |f|
155
+ if f.is_a?(RGen::ECore::EReference) && f.containment
156
+ childs = element.getGeneric(f.name)
157
+ calcQualifiedElementNames(childs, qualifiedNamePath, takenChildNames)
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ def unifyQualifiedElementNames
164
+ @qualifiedElementName.keys.each do |k|
165
+ @qualifiedElementName[k] = @qualifiedElementName[k].sort{|a,b| a.size <=> b.size}.first
166
+ end
167
+ end
168
+
169
+ def calcInternalElementName(element, takenNames)
170
+ return @internalElementName[element] if @internalElementName[element]
171
+ name = if element.respond_to?(:name) && element.name && !element.name.empty?
172
+ element.name
173
+ else
174
+ nextElementHelperName(element)
175
+ end
176
+ while takenNames.include?(name)
177
+ name = nextElementHelperName(element)
178
+ end
179
+ takenNames << name
180
+ @internalElementName[element] = name
181
+ end
182
+
183
+ def nextElementHelperName(element)
184
+ eClass = element.class.ecore
185
+ @nextElementNameId ||= {}
186
+ @nextElementNameId[eClass] ||= 1
187
+ result = "_#{eClass.name}#{@nextElementNameId[eClass]}"
188
+ @nextElementNameId[eClass] += 1
189
+ result
190
+ end
191
+
192
+ def eAllStructuralFeatures(element)
193
+ @eAllStructuralFeatures ||= {}
194
+ @eAllStructuralFeatures[element.class] ||= element.class.ecore.eAllStructuralFeatures
195
+ end
196
+
197
+ end
198
+
199
+ end
200
+
201
+ end