rgen 0.4.6 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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