File: //usr/lib/ruby/site_ruby/1.8/puppet/pops/containment.rb
# FIXME: This module should be updated when a newer version of RGen (>0.6.2) adds required meta model "e-method" supports.
#
require 'rgen/ecore/ecore'
module Puppet::Pops::Containment
# Returns Enumerable, thus allowing
# some_element.eAllContents each {|contained| }
# This is a depth first enumeration where parent appears before children.
# @note the top-most object itself is not included in the enumeration, only what it contains.
def eAllContents
EAllContentsEnumerator.new(self)
end
def eAllContainers
EAllContainersEnumerator.new(self)
end
class EAllContainersEnumerator
include Enumerable
def initialize o
@element = o
end
def each &block
if block_given?
eAllContainers(@element, &block)
else
self
end
end
def eAllContainers(element, &block)
x = element.eContainer
while !x.nil? do
yield x
x = x.eContainer
end
end
end
class EAllContentsEnumerator
include Enumerable
def initialize o
@element = o
@@cache ||= {}
end
def each &block
if block_given?
eAllContents(@element, &block)
@element
else
self
end
end
def eAllContents(element, &block)
# This method is performance critical and code has been manually in-lined.
# Resist the urge to make this pretty.
# The slow way is element.eAllContainments.each {|c| element.getGenericsAsArray(c.name) }
#
(@@cache[element.class] || all_containment_getters(element)).each do |r|
children = element.send(r)
if children.is_a?(Array)
children.each do |c|
yield c
eAllContents(c, &block)
end
elsif !children.nil?
yield children
eAllContents(children, &block)
end
end
end
private
def all_containment_getters(element)
elem_class = element.class
containments = []
collect_getters(elem_class.ecore, containments)
@@cache[elem_class] = containments
end
def collect_getters(eclass, containments)
eclass.eStructuralFeatures.select {|r| r.is_a?(RGen::ECore::EReference) && r.containment}.each do |r|
n = r.name
containments << :"get#{n[0..0].upcase + ( n[1..-1] || "" )}"
end
eclass.eSuperTypes.each do |t|
if cached = @@cache[ t.instanceClass ]
containments.concat(cached)
else
super_containments = []
collect_getters(t, super_containments)
@@cache[ t.instanceClass ] = super_containments
containments.concat(super_containments)
end
end
end
end
end