NAME
Config::Model::ObjTreeScanner - Scan config tree and perform call-backs
VERSION
version 1.228
SYNOPSIS
use Config::Model::ObjTreeScanner ;
# define configuration tree object
my $root = ... ;
# define leaf call back
my disp_leaf = sub {
my ($scanner, $data_ref, $node,$element_name,$index, $leaf_object) = @_ ;
$$data_ref .= "$element_name = ", $leaf_object->fetch ;
} ;
# simple scanner, (print all values with 'beginner' experience
$scan = Config::Model::ObjTreeScanner-> new
(
leaf_cb => \&disp_leaf, # only mandatory parameter
) ;
my $result = '';
$scan->scan_node(\$result, $root) ;
# For a more complex scanner
$scan = Config::Model::ObjTreeScanner-> new
(
fallback => 'none', # all callback must be defined
experience => 'master', # consider all values
# node callback
node_content_cb => \&disp_obj_elt ,
# element callback
list_element_cb => \&disp_hash ,
check_list_element_cb => \&disp_hash ,
hash_element_cb => \&disp_hash ,
node_element_cb => \&disp_obj ,
# leaf callback
leaf_cb => \&disp_leaf,
enum_value_cb => \&disp_leaf,
integer_value_cb => \&disp_leaf,
number_value_cb => \&disp_leaf,
boolean_value_cb => \&disp_leaf,
string_value_cb => \&disp_leaf,
uniline_value_cb => \&disp_leaf,
reference_value_cb => \&disp_leaf,
# call-back when going up the tree
up_cb => sub {} ,
) ;
$scan->scan_node(\$result, $root) ;
DESCRIPTION
This module creates an object that will explore (depth first) a configuration tree.
For each part of the configuration tree, ObjTreeScanner object will call-back one of the subroutine reference passed during construction.
Call-back routines will be called:
For each node containing elements (including root node)
For each element of a node. This element can be a list, hash, node or simple leaf element.
For each item contained in a node, hash or list. This item can be a simple leaf or another node.
To continue the exploration, these call-backs must also call the scanner. (i.e. perform another call-back). In other words the user's subroutine and the scanner plays a game of ping-pong until the tree is completely explored.
The scanner provides a set of default callback for the nodes. This way, the user only have to provide call-backs for the leaves.
The scan is started with a call to scan_node
. The first parameter of scan_node is a ref that is passed untouched to all call-back. This ref may be used to store whatever result you want.
CONSTRUCTOR
new ( ... )
One way or another, the ObjTreeScanner object must be able to find all callback for all the items of the tree. All the possible call-back are listed below:
- leaf callback:
-
leaf_cb
is a catch-all generic callback. All other are specialized call-back :enum_value_cb
,integer_value_cb
,number_value_cb
,boolean_value_cb
,string_value_cb
,uniline_value_cb
,reference_value_cb
- node callback:
-
node_content_cb
- element callback:
-
All these call-backs are called on the elements of a node:
list_element_cb
,check_list_element_cb
,hash_element_cb
,node_element_cb
,node_content_cb
.
The user may specify all of them by passing the sub ref to the constructor:
$scan = Config::Model::ObjTreeScanner-> new
(
# node callback
list_element_cb => sub ,
...
)
Or use some default callback using the fallback parameter. Note that at least one callback must be provided: leaf_cb
.
Optional parameter:
- fallback
-
If set to 'node', the scanner will provide default call-back for node items. If set to 'leaf', the scanner will set all leaf callback (like enum_value_cb ...) to string_value_cb or to the mandatory leaf_cb value. "fallback" callback will not override callbacks provided by the user.
If set to 'all', equivalent to 'node' and 'leaf'. By default, no fallback is provided.
- experience
-
Set the privilege level used for the scan (default 'beginner').
- auto_vivify
-
Whether to create the configuration items while scan (default is 1).
Callback prototypes
Leaf callback
leaf_cb
is called for each leaf of the tree. The leaf callback will be called with the following parameters:
($scanner, $data_ref,$node,$element_name,$index, $leaf_object)
where:
$scanner
is the scanner object.$data_ref
is a reference that is first passed to the first call of the scanner. Then$data_ref
is relayed through the various call-backs$node
is the node that contain the leaf.$element_name
is the element (or attribute) that contain the leaf.$index
is the index (or hash key) used to get the leaf. This may be undefined if the element type is scalar.$leaf_object
is a Config::Model::Value object.
List element callback
list_element_cb
is called on all list element of a node, i.e. call on the list object itself and not in the elements contained in the list.
($scanner, $data_ref,$node,$element_name,@indexes)
@indexes
is a list containing all the indexes of the list.
Example:
sub my_list_element_cb {
my ($scanner, $data_ref,$node,$element_name,@idx) = @_ ;
# custom code using $data_ref
# resume exploration (if needed)
map {$scanner->scan_list($data_ref,$node,$element_name,$_)} @idx ;
# note: scan_list and scan_hash are equivalent
}
Check list element callback
check_list_element_cb
: Like list_element_cb
, but called on a check_list element.
($scanner, $data_ref,$node,$element_name,@check_items)
@check_items
is a list containing all the items of the check_list.
Hash element callback
hash_element_cb
: Like list_element_cb
, but called on a hash element.
($scanner, $data_ref,$node,$element_name,@keys)
@keys
is an list containing all the keys of the hash.
Example:
sub my_hash_element_cb {
my ($scanner, $data_ref,$node,$element_name,@keys) = @_ ;
# custom code using $data_ref
# resume exploration
map {$scanner->scan_hash($data_ref,$node,$element_name,$_)} @keys ;
}
Node content callback
node_content_cb
: This call-back is called foreach node (including root node).
($scanner, $data_ref,$node,@element_list)
@element_list
contains all the element names of the node.
Example:
sub my_content_cb = {
my ($scanner, $data_ref,$node,@element) = @_ ;
# custom code using $data_ref
# resume exploration
map {$scanner->scan_element($data_ref, $node,$_)} @element ;
}
Node element callback
node_element_cb
is called for each node contained within a node (i.e not with root node). This node can be held by a plain element or a hash element or a list element:
($scanner, $data_ref,$node,$element_name,$key, $contained_node)
$key
may be undef if $contained_node
is not a part of a hash or a list. $element_name
and $key
specifies the element name and key of the the contained node you want to scan. (passed with $contained_node
) Note that $contained_node
may be undef if auto_vivify
is 0.
Example:
sub my_node_element_cb {
my ($scanner, $data_ref,$node,$element_name,$key, $contained_node) = @_;
# your custom code using $data_ref
# explore next node
$scanner->scan_node($data_ref,$contained_node);
}
METHODS
scan_node ($data_r,$node)
Explore the node and call node_element_cb
passing all element names.
scan_element($data_r,$node,$element_name)
Explore the element and call either hash_element_cb
, list_element_cb
, node_content_cb
or a leaf call-back (the leaf call-back called depends on the Value object properties: enum, string, integer and so on)
scan_hash ($data_r,$node,$element_name,$key)
Explore the hash member (or hash value) and call either node_content_cb
or a leaf call-back.
scan_list ($data_r,$node,$element_name,$index)
Just like scan_hash
: Explore the list member and call either node_content_cb
or a leaf call-back.
get_keys ($node, $element_name)
Returns an list containing the sorted keys of a hash element or returns an list containning (0.. last_index) of an list element.
Throws an exception if element is not an list or a hash element.
experience ( [ new_experience ] )
Set or query the experience level of the scanner
get_experience_ref ( )
Get a SCALAR reference on experience. Use with care.
AUTHOR
Dominique Dumont, (ddumont at cpan dot org)
SEE ALSO
Config::Model,Config::Model::Node,Config::Model::Instance, Config::Model::HashId, Config::Model::ListId, Config::Model::CheckList, Config::Model::Value