NAME
Config::Model::ObjTreeScanner - Scan config tree and perform call-backs
VERSION
version 1.249
SYNOPSIS
use Config::Model ;
use Log::Log4perl qw(:easy) ;
Log::Log4perl->easy_init($WARN);
# define configuration tree object
my $model = Config::Model->new ;
$model ->create_config_class (
name => "MyClass",
element => [
[qw/foo bar/] => {
type => 'leaf',
value_type => 'string'
},
baz => {
type => 'hash',
index_type => 'string' ,
cargo => {
type => 'leaf',
value_type => 'string',
},
},
],
) ;
my $inst = $model->instance(root_class_name => 'MyClass' );
my $root = $inst->config_root ;
# put some data in config tree the hard way
$root->fetch_element('foo')->store('yada') ;
$root->fetch_element('bar')->store('bla bla') ;
$root->fetch_element('baz')->fetch_with_id('en')->store('hello') ;
# put more data the easy way
my $step = 'baz:fr=bonjour baz:hr="dobar dan"';
$root->load( step => $step ) ;
# define leaf call back
my $disp_leaf = sub {
my ($scanner, $data_ref, $node,$element_name,$index, $leaf_object) = @_ ;
$$data_ref .= "disp_leaf called for '". $leaf_object->name.
"' value '".$leaf_object->fetch."'\n";
} ;
# simple scanner, (print all values with 'beginner' experience
my $scan = Config::Model::ObjTreeScanner-> new (
leaf_cb => $disp_leaf, # only mandatory parameter
) ;
my $result = '';
$scan->scan_node(\$result, $root) ;
print $result ;
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 play 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
,node_dispatch_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 a sub ref to the constructor:
$scan = Config::Model::ObjTreeScanner-> new
(
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).
- check
-
yes
,no
orskip
.
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 ;
}
Dispatch node callback
node_dispatch_cb
: Any callback specified in the hash will be called for each instance of the specified configuration class. (this may include the root node).
For instance, if you have:
node_dispach_cb => {
ClassA => \&my_class_a_dispatch_cb,
ClassB => \&my_class_b_dispatch_cb,
}
&my_class_a_dispatch_cb
will be called for each instance of ClassA
and &my_class_b_dispatch_cb
will be called for each instance of ClassB
.
They will be called with the following parameters:
($scanner, $data_ref,$node,@element_list)
@element_list
contains all the element names of the node.
Example:
sub my_class_a_dispatch_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 either node_dispatch_cb
(if the node class name matches the dispatch_node hash) or (e.g. xor) node_element_cb
passing all element names.
After the first callback has returned, up_cb
will be called.
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 containing (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