Config::Model::ObjTreeScanner.3pm

Langue: en

Version: 2009-05-31 (debian - 07/07/09)

Section: 3 (Bibliothèques de fonctions)

NAME

Config::Model::ObjTreeScanner - Scan config tree and perform call-backs

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'.

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_node_element_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):
  ($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_content_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