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

cache[R]
max_args[R]
message[R]
min_args[R]
receiver[R]

Public Class Methods

new(receiver, message, min_args=0, max_args=nil) click to toggle source
   # 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(thing, *args) click to toggle source

Visit the configured receiver

   # File lib/puppet/pops/visitor.rb
27 def visit(thing, *args)
28   visit_this(@receiver, thing, args)
29 end
visit_this(receiver, thing, args) click to toggle source

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_this_0(receiver, thing) click to toggle source

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_this_1(receiver, thing, arg) click to toggle source

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_this_2(receiver, thing, arg1, arg2) click to toggle source

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_this_3(receiver, thing, arg1, arg2, arg3) click to toggle source

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_this_class(receiver, clazz, args) click to toggle source

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