Class: ConfigToolkit::HashArrayVisitor
- Inherits:
-
Object
- Object
- ConfigToolkit::HashArrayVisitor
- Defined in:
- lib/configtoolkit/hasharrayvisitor.rb
Overview
This class allows each node of an Array or Hash containing arbitrarily deeply nested Arrays or Hashes to be visited. Users extend this class for a particular task and override some or all of the visit_*
, enter_*
, and leave_*
methods to accomplish the task. They then call the visit
method in order to visit the nodes of a structure.
This class was written in order to factor out (fairly complicated) iteration logic from methods that need to process each element of one of these structures. Such methods almost invariably require a stack to store information for all levels above the level currently being processed. Previously, when these methods recursively iterated over these structures, they used the call stack for this purpose. The HashArrayVisitor, however, provides its own stack. All of the enter_*
methods are expected to return a new stack frame for the container being entered, which will be accessible via the stack_top method while processing elements of the container. When the leave_*
method is called for the container, the associated stack frame will be popped from the top of the stack and passed to the leave_*
method. An initial stack frame can be specified in new, which often is handy as it ensures that there always will be at least one element in the stack. The HashArrayVisitor base class has no knowledge of the contents of a stack frame, and so the stack frames can be of any type (even nil
if no stack is required).
PrettyPrintWriter, YAMLWriter, and KeyValueWriter all use this class.
Direct Known Subclasses
KeyValueWriter::Visitor, OverrideReader::Visitor, PrettyPrintWriter::Visitor, YAMLWriter::Visitor
Instance Method Summary collapse
-
#enter_array(array) ⇒ Object
Description: This method is called when an Array is visited for the first time.
-
#enter_hash(hash) ⇒ Object
Description: This method is called when a Hash is visited for the first time.
-
#initialize(initial_stack_frame = nil) ⇒ HashArrayVisitor
constructor
Description: This constructs the visitor with initial stack frame
initial_stack_frame
. -
#leave_array(popped_stack_frame) ⇒ Object
Description: This method is called when finished visiting all elements of an Array.
-
#leave_hash(popped_stack_frame) ⇒ Object
Description: This method is called when finished visiting all elements of a Hash.
-
#stack_empty? ⇒ Boolean
Returns: True if and only if the stack is empty.
-
#stack_top ⇒ Object
Returns: The top stack frame.
-
#visit(structure) ⇒ Object
Description: This method visits the nodes of
structure
, calling the appropriate method for each node. -
#visit_array_element(value, index, is_container_value) ⇒ Object
Description: This method is called when visiting an Array element
value
atindex
in the Array. -
#visit_hash_element(key, value, index, is_container_value) ⇒ Object
Description: This method is called when visiting a Hash element mapping
key
tovalue
.
Constructor Details
#initialize(initial_stack_frame = nil) ⇒ HashArrayVisitor
Description:
This constructs the visitor with initial stack frame initial_stack_frame
.
Parameters:
- initial_stack_frame
-
The initial stack frame; if not specified, then the stack initially will be empty. Specifying an initial stack frame ensures that the stack never will be empty while visiting a structure (this frame never will be popped).
44 45 46 47 48 49 50 |
# File 'lib/configtoolkit/hasharrayvisitor.rb', line 44 def initialize(initial_stack_frame = nil) @stack = [] if(initial_stack_frame != nil) @stack.push(initial_stack_frame) end end |
Instance Method Details
#enter_array(array) ⇒ Object
Description:
This method is called when an Array is visited for the first time. It must return the new stack frame for the Array.
This can be overridden; the default implementation is a no-op and returns nil
.
Parameters:
- array
-
The Array being visited
Returns:
The new stack frame for the Array
200 201 202 |
# File 'lib/configtoolkit/hasharrayvisitor.rb', line 200 def enter_array(array) return nil end |
#enter_hash(hash) ⇒ Object
Description:
This method is called when a Hash is visited for the first time. It must return the new stack frame for the Hash.
This can be overridden; the default implementation is a no-op and returns nil
.
Parameters:
- hash
-
The Hash being visited
Returns:
The new stack frame for the Hash
141 142 143 |
# File 'lib/configtoolkit/hasharrayvisitor.rb', line 141 def enter_hash(hash) return nil end |
#leave_array(popped_stack_frame) ⇒ Object
Description:
This method is called when finished visiting all elements of an Array. The stack will be popped before the call (so stack_top will return the frame for the Array’s parent), but the popped stack frame is passed as popped_stack_frame
.
This can be overridden; the default implementation is a no-op.
Parameters:
- popped_stack_frame
-
The stack frame associated with the Array, which has been popped from the stack.
218 219 |
# File 'lib/configtoolkit/hasharrayvisitor.rb', line 218 def leave_array(popped_stack_frame) end |
#leave_hash(popped_stack_frame) ⇒ Object
Description:
This method is called when finished visiting all elements of a Hash. The stack will be popped before the call (so stack_top will return the frame for the Hash’s parent), but the popped stack frame is passed as popped_stack_frame
.
This can be overridden; the default implementation is a no-op.
Parameters:
- popped_stack_frame
-
The stack frame associated with the Hash, which has been popped from the stack.
159 160 |
# File 'lib/configtoolkit/hasharrayvisitor.rb', line 159 def leave_hash(popped_stack_frame) end |
#stack_empty? ⇒ Boolean
Returns:
True if and only if the stack is empty
122 123 124 |
# File 'lib/configtoolkit/hasharrayvisitor.rb', line 122 def stack_empty? return @stack.empty?() end |
#stack_top ⇒ Object
Returns:
The top stack frame
114 115 116 |
# File 'lib/configtoolkit/hasharrayvisitor.rb', line 114 def stack_top return @stack[-1] end |
#visit(structure) ⇒ Object
Description:
This method visits the nodes of structure
, calling the appropriate method for each node.
Parameters:
- structure
-
The Hash or Array whose nodes are to be visited (if
structure
‘s nodes themselves are Arrays or Hashes, the nodes of these nested structures also will be visited).
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 101 102 103 104 105 106 107 108 |
# File 'lib/configtoolkit/hasharrayvisitor.rb', line 72 def visit(structure) if(structure.is_a?(Hash)) @stack.push(enter_hash(structure)) structure.each_with_index do |key_value, index| key = key_value[0] value = key_value[1] is_container_value = container_value?(value) visit_hash_element(key, value, index, is_container_value) if(is_container_value) visit(value) end end leave_hash(@stack.pop()) elsif(structure.is_a?(Array)) @stack.push(enter_array(structure)) structure.each_with_index do |element, index| is_container_value = container_value?(element) visit_array_element(element, index, is_container_value) if(is_container_value) visit(element) end end leave_array(@stack.pop()) else = "The argument to HashArrayVisitor::visit must be a " << "Hash or Array; instead, a #{structure.class} " << "(#{structure}) was passed!" raise ArgumentError, end end |
#visit_array_element(value, index, is_container_value) ⇒ Object
Description:
This method is called when visiting an Array element value
at index
in the Array.
This can be overridden; the default implementation is a no-op.
Parameters:
- value
-
The Array element
- index
-
The index of
value
in the Array - is_container_value
-
Whether or not
value
is a container (in which case, it will be visited next with a call toenter_array
orenter_hash
)
238 239 |
# File 'lib/configtoolkit/hasharrayvisitor.rb', line 238 def visit_array_element(value, index, is_container_value) end |
#visit_hash_element(key, value, index, is_container_value) ⇒ Object
Description:
This method is called when visiting a Hash element mapping key
to value
.
This can be overridden; the default implementation is a no-op.
Parameters:
- key
-
The key in the Hash element
- value
-
The value in the Hash element
- index
-
The index of key=>value in the Hash (the index that is returned by
each_with_index
) - is_container_value
-
Whether or not
value
is a container (in which case, it will be visited next with a call toenter_array
orenter_hash
)
182 183 |
# File 'lib/configtoolkit/hasharrayvisitor.rb', line 182 def visit_hash_element(key, value, index, is_container_value) end |