class Puppet::Pops::Visitor
A Visitor
performs delegation to a given receiver based on the configuration of the Visitor
. A new visitor is created with a given receiver, a method prefix, min, and max argument counts. e.g.
visitor = Visitor.new(self, "visit_from", 1, 1)
will make the visitor call “self.visit_from_CLASS(x)” where CLASS is resolved to the given objects class, or one of is ancestors, the first class for which there is an implementation of a method will be selected.
Raises RuntimeError if there are too few or too many arguments, or if the receiver is not configured to handle a given visiting object.
Constants
- NO_ARGS
Attributes
Public Class Methods
# File lib/puppet/pops/visitor.rb 15 def initialize(receiver, message, min_args=0, max_args=nil) 16 raise ArgumentError.new("min_args must be >= 0") if min_args < 0 17 raise ArgumentError.new("max_args must be >= min_args or nil") if max_args && max_args < min_args 18 19 @receiver = receiver 20 @message = message 21 @min_args = min_args 22 @max_args = max_args 23 @cache = Hash.new 24 end
Public Instance Methods
Visit the configured receiver
# File lib/puppet/pops/visitor.rb 27 def visit(thing, *args) 28 visit_this(@receiver, thing, args) 29 end
Visit an explicit receiver
# File lib/puppet/pops/visitor.rb 34 def visit_this(receiver, thing, args) 35 raise "Visitor Error: Too few arguments passed. min = #{@min_args}" unless args.length >= @min_args 36 if @max_args 37 raise "Visitor Error: Too many arguments passed. max = #{@max_args}" unless args.length <= @max_args 38 end 39 method_name = @cache[thing.class] 40 if method_name 41 return receiver.send(method_name, thing, *args) 42 else 43 thing.class.ancestors().each do |ancestor| 44 name = ancestor.name 45 next if name.nil? 46 method_name = :"#{@message}_#{name.split(DOUBLE_COLON).last}" 47 next unless receiver.respond_to?(method_name, true) 48 @cache[thing.class] = method_name 49 return receiver.send(method_name, thing, *args) 50 end 51 end 52 raise "Visitor Error: the configured receiver (#{receiver.class}) can't handle instance of: #{thing.class}" 53 end
Visit an explicit receiver with 0 args (This is ~30% faster than calling the general method)
# File lib/puppet/pops/visitor.rb 80 def visit_this_0(receiver, thing) 81 method_name = @cache[thing.class] 82 if method_name 83 return receiver.send(method_name, thing) 84 end 85 visit_this(receiver, thing, NO_ARGS) 86 end
Visit an explicit receiver with 1 args (This is ~30% faster than calling the general method)
# File lib/puppet/pops/visitor.rb 91 def visit_this_1(receiver, thing, arg) 92 method_name = @cache[thing.class] 93 if method_name 94 return receiver.send(method_name, thing, arg) 95 end 96 visit_this(receiver, thing, [arg]) 97 end
Visit an explicit receiver with 2 args (This is ~30% faster than calling the general method)
# File lib/puppet/pops/visitor.rb 102 def visit_this_2(receiver, thing, arg1, arg2) 103 method_name = @cache[thing.class] 104 if method_name 105 return receiver.send(method_name, thing, arg1, arg2) 106 end 107 visit_this(receiver, thing, [arg1, arg2]) 108 end
Visit an explicit receiver with 3 args (This is ~30% faster than calling the general method)
# File lib/puppet/pops/visitor.rb 113 def visit_this_3(receiver, thing, arg1, arg2, arg3) 114 method_name = @cache[thing.class] 115 if method_name 116 return receiver.send(method_name, thing, arg1, arg2, arg3) 117 end 118 visit_this(receiver, thing, [arg1, arg2, arg3]) 119 end
Visit an explicit receiver
# File lib/puppet/pops/visitor.rb 56 def visit_this_class(receiver, clazz, args) 57 raise "Visitor Error: Too few arguments passed. min = #{@min_args}" unless args.length >= @min_args 58 if @max_args 59 raise "Visitor Error: Too many arguments passed. max = #{@max_args}" unless args.length <= @max_args 60 end 61 method_name = @cache[clazz] 62 if method_name 63 return receiver.send(method_name, clazz, *args) 64 else 65 clazz.ancestors().each do |ancestor| 66 name = ancestor.name 67 next if name.nil? 68 method_name = :"#{@message}_#{name.split(DOUBLE_COLON).last}" 69 next unless receiver.respond_to?(method_name, true) 70 @cache[clazz] = method_name 71 return receiver.send(method_name, clazz, *args) 72 end 73 end 74 raise "Visitor Error: the configured receiver (#{receiver.class}) can't handle instance of: #{clazz}" 75 end