Class: RGen::ModelBuilder::BuilderContext

Inherits:
Object
  • Object
show all
Defined in:
lib/rgen/model_builder/builder_context.rb

Defined Under Namespace

Classes: CommandResolver, ConstPathElement, ExtensionContainerFactory, PackageNotFoundException, PackageResolver

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(package, extensionsModule, resolver, env = nil) ⇒ BuilderContext

Returns a new instance of BuilderContext.



11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/rgen/model_builder/builder_context.rb', line 11

def initialize(package, extensionsModule, resolver, env=nil)
  package = package.ecore unless package.is_a?(RGen::ECore::EPackage)
  raise "First argument must be a metamodel package" \
    unless package.is_a?(RGen::ECore::EPackage)
  @rootPackage, @env = package, env
  @commandResolver = CommandResolver.new(package, extensionsModule, self)
  @package = @rootPackage
  @resolver = resolver
  @contextStack = []
  @toplevelElements = []
  @helperNames = {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args, &block) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/rgen/model_builder/builder_context.rb', line 68

def method_missing(m, *args, &block)
  package, classOrContainer = @commandResolver.resolveCommand(m, @package)
  return super if package.nil?
  return classOrContainer.send(m, *args, &block) if classOrContainer.is_a?(ExtensionContainerFactory::ExtensionContainer)
  eClass = classOrContainer
  nameArg, argHash = self.class.processArguments(args)
  internalName = nameArg || argHash[:name]
  argHash[:name] ||= nameArg if nameArg && self.class.hasNameAttribute(eClass)
  resolverJobs, asRole, helperName = self.class.filterArgHash(argHash, eClass)
  element = eClass.instanceClass.new(argHash)
  @resolver.setElementName(element, internalName)
  @env << element if @env
  contextElement = @contextStack.last
  if contextElement
    self.class.associateWithContextElement(element, contextElement, asRole)
  else
    @toplevelElements << element
  end
  resolverJobs.each do |job|
    job.receiver = element
    job.namespace = contextElement
    @resolver.addJob(job)
  end
  # process block
  if block
    @contextStack.push(element)
    @package, oldPackage = package, @package
    instance_eval(&block)
    @package = oldPackage
    @contextStack.pop
  end
  element
end

Instance Attribute Details

#toplevelElementsObject (readonly)

Returns the value of attribute toplevelElements.



9
10
11
# File 'lib/rgen/model_builder/builder_context.rb', line 9

def toplevelElements
  @toplevelElements
end

Class Method Details

.associateWithContextElement(element, contextElement, asRole) ⇒ Object



303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/rgen/model_builder/builder_context.rb', line 303

def associateWithContextElement(element, contextElement, asRole)
  return unless contextElement
  contextClass = contextElement.class.ecore
  if asRole
    asRoleRef = eAllReferences(contextClass).find{|r| r.name == asRole.to_s}
    raise "Context class #{contextClass.name} has no reference named #{asRole}" unless asRoleRef
    ref = asRoleRef
  else
    possibleContainmentRefs = containmentRefs(contextClass, element.class.ecore)
    if possibleContainmentRefs.size == 1
      ref = possibleContainmentRefs.first
    elsif possibleContainmentRefs.size == 0
      raise "Context class #{contextClass.name} can not contain a #{element.class.ecore.name}"
    else
      raise "Context class #{contextClass.name} has several containment references to a #{element.class.ecore.name}." +
        " Clearify using \":as => <role>\""
    end
  end
  if ref.many
    contextElement.addGeneric(ref.name, element)
  else
    contextElement.setGeneric(ref.name, element)
  end
end

.const_missing(name) ⇒ Object



35
36
37
38
39
40
41
# File 'lib/rgen/model_builder/builder_context.rb', line 35

def const_missing(name)
  if @@currentBuilderContext
    ConstPathElement.new(name, @@currentBuilderContext)
  else
    super
  end
end

.containmentRefs(contextClass, eClass) ⇒ Object



295
296
297
298
299
300
301
# File 'lib/rgen/model_builder/builder_context.rb', line 295

def containmentRefs(contextClass, eClass)
  @containmentRefs ||= {}
  @containmentRefs[[contextClass, eClass]] ||=
    eAllReferences(contextClass).select do |r| 
      r.containment && (eClass.eAllSuperTypes << eClass).include?(r.eType)
    end
end

.currentBuilderContext=(bc) ⇒ Object



31
32
33
# File 'lib/rgen/model_builder/builder_context.rb', line 31

def currentBuilderContext=(bc)
 @@currentBuilderContext = bc
end

.eAllReferences(eClass) ⇒ Object



290
291
292
293
# File 'lib/rgen/model_builder/builder_context.rb', line 290

def eAllReferences(eClass)
  @eAllReferences ||= {}
  @eAllReferences[eClass] ||= eClass.eAllReferences
end

.filterArgHash(argHash, eClass) ⇒ Object



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/rgen/model_builder/builder_context.rb', line 254

def filterArgHash(argHash, eClass)
  resolverJobs = []
  asRole, helperName = nil, nil
  refByName = {}
  eAllReferences(eClass).each {|r| refByName[r.name] = r}
  argHash.each_pair do |k,v|
    if k == :as
      asRole = v
      argHash.delete(k)
    elsif k == :name && !hasNameAttribute(eClass)
      helperName = v          
      argHash.delete(k)
    elsif v.is_a?(String)
      ref = refByName[k.to_s]#eAllReferences(eClass).find{|r| r.name == k.to_s}
      if ref
        argHash.delete(k)
        resolverJobs << ReferenceResolver::ResolverJob.new(nil, ref, nil,  v)
      end
    elsif v.is_a?(Array)
      ref = refByName[k.to_s] #eAllReferences(eClass).find{|r| r.name == k.to_s}
      ref && v.dup.each do |e|
        if e.is_a?(String)
          v.delete(e)
          resolverJobs << ReferenceResolver::ResolverJob.new(nil, ref, nil, e)
        end
      end
    end
  end
  [ resolverJobs, asRole, helperName ]
end

.hasNameAttribute(eClass) ⇒ Object



285
286
287
288
# File 'lib/rgen/model_builder/builder_context.rb', line 285

def hasNameAttribute(eClass)
  @hasNameAttribute ||= {}
  @hasNameAttribute[eClass] ||= eClass.eAllAttributes.any?{|a| a.name == "name"}
end

.processArguments(args) ⇒ Object



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/rgen/model_builder/builder_context.rb', line 237

def processArguments(args)
  unless (args.size == 2 && args.first.is_a?(String) && args.last.is_a?(Hash)) ||
    (args.size == 1 && (args.first.is_a?(String) || args.first.is_a?(Hash))) ||
    args.size == 0
    raise "Provide a Hash to set feature values, " +
      "optionally the first argument may be a String specifying " + 
      "the value of the \"name\" attribute."
  end
  if args.last.is_a?(Hash)
    argHash = args.last
  else
    argHash = {}
  end
  nameArg = args.first if args.first.is_a?(String)
  [nameArg, argHash]
end

.resolvePackage(contextPackage, rootPackage, path) ⇒ Object



214
215
216
217
218
219
220
221
222
223
224
# File 'lib/rgen/model_builder/builder_context.rb', line 214

def resolvePackage(contextPackage, rootPackage, path)
  begin
    return resolvePackageDownwards(contextPackage, path)
  rescue PackageNotFoundException
    if contextPackage.eSuperPackage && contextPackage != rootPackage
      return resolvePackage(contextPackage.eSuperPackage, rootPackage, path)
    else
      raise
    end
  end
end

.resolvePackageDownwards(contextPackage, path) ⇒ Object



226
227
228
229
230
231
232
233
234
235
# File 'lib/rgen/model_builder/builder_context.rb', line 226

def resolvePackageDownwards(contextPackage, path)
  first, *rest = path
  package = contextPackage.eSubpackages.find{|p| p.name == first}
  raise PackageNotFoundException.new("Could not resolve package: #{first} is not a subpackage of #{contextPackage.name}") unless package
  if rest.empty?
    package 
  else
    resolvePackageDownwards(package, rest)
  end
end

Instance Method Details

#_context(depth = 1) ⇒ Object



109
110
111
# File 'lib/rgen/model_builder/builder_context.rb', line 109

def _context(depth=1)
  @contextStack[-depth]
end

#_using(constPathElement, &block) ⇒ Object



102
103
104
105
106
107
# File 'lib/rgen/model_builder/builder_context.rb', line 102

def _using(constPathElement, &block)
  @package, oldPackage = 
    self.class.resolvePackage(@package, @rootPackage, constPathElement.constPath), @package
  instance_eval(&block)
  @package = oldPackage
end

#const_missing_delegated(delegator, const) ⇒ Object



24
25
26
# File 'lib/rgen/model_builder/builder_context.rb', line 24

def const_missing_delegated(delegator, const)
  ConstPathElement.new(const, self)
end