The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

 Config::Hierarchical - Hierarchical configuration container

SYNOPSIS

  use Config::Hierarchical ;
   
  my $config = new Config::Hierarchical(); 
  
  # or
  
  my $config = new Config::Hierarchical
                        (
                        NAME                       => 'some_namespace',
                        VERBOSE                    => 0,
                        DISABLE_SILENT_OPTIONS     => 0,
                        CATEGORY_NAMES             => ['<CLI>', '<PBS>', 'PARENT', 'LOCAL', 'CURRENT'],
                        DEFAULT_CATEGORY           => 'CURRENT',
                        
                        WARN_FOR_EXPLICIT_CATEGORY => 0,
                        
                        GET_CATEGORIES => 
                                {
                                Inheritable => ['CLI', 'PBS', 'PARENT', 'CURRENT'],
                                },
                                
                        INTERACTION =>
                                {
                                INFO  => \&sub,
                                WARN  => \&sub,
                                DIE   => \&sub,
                                DEBUG => \&sub,
                                },
                                
                        VALIDATORS =>
                                [
                                {
                                CATEGORY_NAMES => ['CLI', 'CURRENT',] ,
                                NAMES          => ['CC', 'LD'],
                                VALIDATORS     => 
                                        {
                                        alphanumeric => \&alphanumeric,
                                        other_validator => \&other_validator,
                                        },
                                },
                                
                                {
                                CATEGORY_NAMES => ['CURRENT',] ,
                                NAMES          => ['CC',],
                                VALIDATORS     => {only_gcc => \&only_gcc,},
                                }, 
                                ],
                                
                        INITIAL_VALUES =>
                                [
                                {
                                CATEGORY => 'PBS',
                                ALIAS    => $pbs_config,
                                HISTORY  => ....,
                                COMMENT  => ....,
                                },
                                
                                {CATEGORY => 'CLI', NAME => 'CC', VALUE => 1,},
                                [CATEGORY => 'CLI', NAME => 'LD', VALUE => 2, LOCK => 1},
                                
                                {CATEGORY => 'CURRENT', NAME => 'CC', VALUE => 3, OVERRIDE => 1},
                                {CATEGORY => 'CURRENT', NAME => 'AS', VALUE => 4,},
                                {CATEGORY => 'CURRENT', NAME => 'VARIABLE_WITH_HISTORY', VALUE => $previous_value, HISTORY => $history },
                                ] ,
                                
                        LOCKED_CATEGORIES => ['CLI'],
                        ) ;
        
  $config->Set(NAME => 'CC', VALUE => 'gcc') ;
  $config->Set(NAME => 'CC', VALUE => 'gcc', CATEGORY => 'CLI') ;
  $config->Set(NAME => 'CC', VALUE => 'gcc', FORCE_LOCK => 1) ;
  $config->Set(NAME => 'CC', VALUE => 'gcc', LOCK => 1) ;
  $config->Set(NAME => 'CC', VALUE => 'gcc', SILENT_OVERRIDE => 1) ;
  $config->Set(NAME => 'CC', VALUE => 'gcc', COMMENT => 'we prefer gcc') ;
  $config->Set(NAME => 'CC', VALUE => 'gcc', CHECK_LOWER_LEVEL_CATEGORIES => 1) ;
  
  $config->Exists(NAME => 'CC') ;
  
  $config->GetKeyValueTuples() ;
  
  $config->SetMultiple
        (
        {FORCE_LOCK => 1}
        {NAME => 'CC', VALUE => 'gcc', SILENT_OVERRIDE => 1},
        {NAME => 'LD', VALUE => 'ld'},
        ) ;
  
  $config->Set(CC => 'gcc') ;
  
  $value = $config->Get(NAME => 'CC') ;
  $value = $config->Get(NAME => 'NON_EXISTANT', SILENT_NOT_EXISTS => 1) ;
  
  @values = $config->GetMultiple(@config_variables_names) ;
  @values = $config->GetMultiple({SILENT_NOT_EXISTS => 1}, @config_variables_names) ;
  
  $hash_ref = $config->GetHashRef() ; # no warnings
  
  $config->GetInheritable() ;
  
  $config->SetDisableSilentOptions(1) ;
        
  $config->LockCategories('PBS') ;
  $config->UnlockCategories('CLI', 'PBS') ;
  $config->IsCategoryLocked('PBS') ;
  
  $config->Lock(NAME => 'CC') ;
  $config->Unlock(NAME => 'CC', CATEGORY => 'CLI') ;
  $config->IsLocked(NAME => 'CC') ;
  
  $history = $config->GetHistory(NAME => 'CC') ;
  $dump = $config->GetDump() ;
  

DESCRIPTION

This module implements a configuration variable container. The container has multiple categories which are declared in decreasing priority order.

A variable can exist in multiple categories within the container. When queried for a variable, the container will return the variable in the category with the highest priority.

When setting a variable, the container will display a warning message if it is set in a category with lower priority than a category already containing the same variable.

Priority overriding is also possible.

DOCUMENTATION

I'll start by giving a usage example. In a build system, configuration variables can have different source.

  • the build tool

  • the command line

  • the parent build file (in a hierarchical build system)

  • the current build file

It is likely that a configuration variable set on the command line should be used regardless of a local setting. Also, a configuration variable set by the build tool itself should have the highest priority.

Among the most difficult errors to find are configuration errors in complex build systems. Build tools generally don't help much when variables are overridden. it's also difficult to get a variable's history.

This module provides the necessary functionality to handle most of the cases needed in a modern build system.

(Test t/099_cookbook.t is also a cookbook you can generate with POD::Tested)

SUBROUTINES/METHODS

new

Create a Config::Hierarchical .

  my $config = new Config::Hierarchical() ;
  
  my $config = new Config::Hierarchical(OPTIONS) ;  

Options

The options are named, the order is not important.

  my $config = new Config::Hierarchical(NAME => 'some_namespace', VERBOSE  => 1) ;
  • NAME

    A string that will be used in all the dumps and interaction with the user.

  • CATEGORY_NAMES

    A list of category names. The first named category has the highest priority. Only categories listed in this list can be manipulated. Using an unregistered category in a Set or Get operation will generate an error.

      my $config = new Config::Hierarchical
                            (
                            CATEGORY_NAMES   => ['CLI', '<PBS>', 'PARENT', 'CURRENT', 'LOCAL'],     
                            DEFAULT_CATEGORY => 'CURRENT',
                            ) ;

    A category can be protected by enclosing its name in angle bracket, IE: <PBS>. Protected categories will not be overridden by lesser priority categories even if the OVERRIDE option is used.

    If no category names are given, 'CURRENT' will be used and DEFAULT_CATEGORY will be set accordingly.

  • DEFAULT_CATEGORY

    The name of the category used when Set is called without a CATEGORY argument.

    If the CATEGORY_NAMES list contains more than one entry, DEFAULT_CATEGORY must be set or an error will be generated.

  • DISABLE_SILENT_OPTIONS

      my $config = new Config::Hierarchical(NAME => 'some_namespace', DISABLE_SILENT_OPTIONS => 1) ;

    When this option is set, SILENT_OVERRIDE and SILENT_NOT_EXISTS will be ignored and Config::Hierarchical will display a warning.

  • GET_CATEGORIES

    This option allows you to define functions that fetch variables in a specific category list and in a specific order.

      my $config = new Config::Hierarchical
                            (
                            CATEGORY_NAMES   => ['CLI', '<PBS>', 'PARENT', 'CURRENT', 'LOCAL'],
                            
                            GET_CATEGORIES =>
                                    {
                                    Inheritable => ['CLI', 'PBS', 'PARENT', 'CURRENT'],
                                    }
                            ...
                            ) ;
                            
      my $value = $config->GetInheritable(NAME => 'CC') ;
      my $hash_ref = $config->GetInheritableHashRef() ;
      

    In the example above, the LOCAL category will not be used by GetInheritable.

  • WARN_FOR_EXPLICIT_CATEGORY

    if set, Config::Hierarchical will display a warning if any category is specified in Get or Set.

  • VERBOSE

    This module will display information about its actions when this option is set. See INTERACTION.

    See SetDisplayExplicitCategoryWarningOption.

  • INTERACTION

    Lets you define subs used to interact with the user.

      my $config = new Config::Hierarchical
                            (
                            INTERACTION      =>
                                    {
                                    INFO  => \&sub,
                                    WARN  => \&sub,
                                    DIE   => \&sub,
                                    DEBUG => \&sub,
                                    }
                            ) ;
    INFO

    This sub will be used when displaying verbose information.

    WARN

    This sub will be used when a warning is displayed. e.g. a configuration that is refused or an override.

    DIE

    Used when an error occurs. E.g. a locked variable is set.

    DEBUG

    If this option is set, Config::Hierarchical will call the sub before and after acting on the configuration. This can act as a breakpoint in a debugger or allows you to pinpoint a configuration problem.

    The functions default to:

    • INFO => CORE::print

    • WARN => Carp::carp

    • DIE => Carp::confess

  • FILE and LINE

    These will be used in the information message and the history information if set. If not set, the values returned by caller will be used. These options allow you to write wrapper functions that report the callers location properly.

  • INITIAL_VALUES

    Lets you initialize the Config::Hierarchical object. Each entry will be passed to Set.

      my $config = new Config::Hierarchical
                            (
                            ...
                            INITIAL_VALUES =>
                                    [
                                    { # aliased category
                                    CATEGORY => 'PBS',
                                    ALIAS    => $pbs_config,
                                    HISTORY  => ....,
                                    COMMENT  => ....,
                                    },
                                    
                                    {CATEGORY => 'CLI', NAME => 'CC', VALUE => 1},
                                    {CATEGORY => 'CLI', NAME => 'LD', VALUE => 2, LOCK => 1},
                                    
                                    {CATEGORY => 'CURRENT', NAME => 'CC', VALUE => 3, OVERRIDE => 1},
                                    {CATEGORY => 'CURRENT', NAME => 'AS', VALUE => 4,},
                                    } ,
                            ) ;

    See Set for options to INITIAL_VALUES.

    Aliased categories allow you to use a category to refer to an existing Config::Hierarchical object. The referenced object is read only. This is because multiple configurations might alias to the same Config::Hierarchical object.

    Variables from aliased category can also be overridden.

  • LOCKED_CATEGORIES

    Lets you lock categories making them read only. values in INITIAL_VALUES are used before locking the category.

      my $config = new Config::Hierarchical
                            (
                            ...
                            LOCKED_CATEGORIES => ['CLI', 'PBS'],
                            ) ;

    See LockCategories and IsCategoryLocked.

  • VALIDATORS

      my $config = new Config::Hierarchical
                            (
                            ...
                            VALIDATORS =>
                                    [
                                    {
                                    CATEGORY_NAMES => ['CURRENT', 'OTHER'] ,
                                    NAMES          => ['CC', 'LD'],
                                    VALIDATORS     => 
                                            {
                                            validator_name => \&PositiveValueValidator,
                                            other_validator => \&SecondValidator
                                            },
                                    },
                                    ],
                            ) ;

    Let you add validation subs to Config::Hierarchical. Each variable in NAMES in each category in CATEGORY_NAMES will be assigned the validators defined in Validators.

    The example above will add a validator PositiveValueValidator and validator SecondValidator to CURRENT::CC, CURRENT::LD, OTHER::CC and OTHER::LD.

    A validator is sub that will be called every time a value is assigned to a variable. The sub is passed a single argument, the value to be assigned to the variable. If false is returned by any of the validators, an Exception will be raised through INTERACTION::DIE.

    see AddValidator.

GetInformation

Returns the configuration name and it's creation location.

Setup

Helper sub called by new. This shall not be used directly.

SetupCategories

Helper sub called by new. This shall not be used directly.

AddValidator

        $config->AddValidator
                        (
                        CATEGORY_NAMES => ['CLI'] ,
                        NAMES          => ['CC', 'LD'],
                        VALIDATORS     => {positive_value => \&PositiveValueValidator},
                        ) ;

You can add validators after creating a configuration and even after adding variables to your configuration. The existing variables will be checked after the validators are added.

Arguments

  • CATEGORY_NAMES, a reference to an array containing the names of the categories to add the validators to

  • NAMES, a reference to an array containing the names of the variables that will be validated

  • VALIDATORS, a reference to a hash containing tuple of validator_name = validator_code_ref>

Config::Hierarchical will warn you if you override a validator.

AddValidators

This shall not be used directly.

AddVariableValidator

This shall not be used directly.

SetAlias

Used to handle category aliases. This shall not be used directly.

  my $pbs_config = new Config::Hierarchical(...) ;
  
  my $config = new Config::Hierarchical
                        (
                        NAME                       => 'some_namespace',
                        CATEGORY_NAMES             => ['<CLI>', '<PBS>', 'PARENT', 'LOCAL', 'CURRENT'],
                                
                        INITIAL_VALUES =>
                                [
                                {
                                CATEGORY => 'PBS',
                                ALIAS    => $pbs_config,
                                HISTORY  => ....,
                                COMMENT  => ....,
                                },
                                {NAME => 'CC1', VALUE => 'gcc'},
                                ...
                                ] ,
                                
                        ) ;

CATEGORY and ALIAS must be passed as arguments. See new for details about aliased categories.

Options

  • HISTORY

  • COMMENT

  • CHECK_LOWER_LEVEL_CATEGORIES

    See Set for details.

CreateCustomGetFunctions

Creates custom Get* functions. This shall not be used directly.

CheckOptionNames

Verifies the options passed to the members of this class. Calls {INTERACTION}{DIE} in case of error. This shall not be used directly.

Set

  my $config = new Config::Hierarchical() ;
  
  $config->Set(NAME => 'CC', VALUE => 'gcc') ;
  
  $config->Set
                (
                NAME => 'CC', VALUE => 'gcc',
                
                # options
                HISTORY         => $history,
                COMMENT         => 'we like gcc'
                CATEGORY        => 'CLI',
                VALIDATORS      => {positive_value => \&PositiveValueValidator,}
                FORCE_LOCK      => 1,
                LOCK            => 1,
                OVERRIDE        => 1,
                SILENT_OVERRIDE => 1,
                ATTRIBUTE       => 'some attribute',
                FILE            => 'some_file',
                LINE            => 1,
                
                CHECK_LOWER_LEVEL_CATEGORIES => 1,
                ) ;

NAME and VALUE must be passed as arguments.

Options

  • HISTORY

    The argument passed is kept in the configuration variable. You can pass any scalar variable; Config::Hierarchical will not manipulate this information.

    See GetHistory.

  • COMMENT

    The comment will be added to the variable history.

  • CATEGORY

    The name of the category where the variable resides. If no CATEGORY is given, the default category is used.

  • ATTRIBUTE

    Set the configuration variable's attribute to the passed argument. See <SetAttribute>.

  • VALIDATORS

    Extra validators that will only be used during this call to Set.

  • FORCE_LOCK

    If a variable is locked, trying to set it will generate an error. It is possible to temporarily force the lock with this option. A warning is displayed when a lock is forced.

  • LOCK

    Will lock the variable if set to 1, unlock if set to 0.

  • OVERRIDE

    This allows the variable in a category to override the variable in a category with higher priority. Once a variable is overridden, it's value will always be the override value even if it is set again.

            my $config = new Config::Hierarchical
                                    (
                                    NAME => 'Test config',
                                    
                                    CATEGORY_NAMES         => ['PARENT', 'CURRENT'],
                                    DEFAULT_CATEGORY       => 'CURRENT',
                                                    
                                    INITIAL_VALUES  =>
                                            [
                                            {NAME => 'CC', CATEGORY => 'PARENT', VALUE => 'parent'},
                                            ] ,
                                    ) ;
                                    
            $config->Set(NAME => 'CC', CATEGORY => 'CURRENT', OVERRIDE => 1, VALUE => 'current') ;
            $config->Set(NAME => 'CC', CATEGORY => 'PARENT', VALUE => 'parent') ;
            
            $config->Get(NAME => 'CC') ; # will return 'current'
  • SILENT_OVERRIDE

    Disables the warning displayed when overriding a variable.

  • FILE and LINE

    See FILE and LINE in new.

  • CHECK_LOWER_LEVEL_CATEGORIES

    Config::Hierarchical display warnings about all the collisions with higher priority categories. If this option is set, warnings will also be displayed for lower priority categories.

History

Config::Hierarchical will keep a history of all the setting you make. The history can be retrieved with GetHistory. The history is also part of the dump generated by GetDump.

CheckHigherPriorityCategories

Check if a config variable setting overrides a higher priority category. This shall not be used directly.

CheckVariableInCategory

This shall not be used directly.

OverrideVariable

This shall not be used directly.

CheckLowerPriorityCategories

Check if a config variable setting takes precedence over a lower priority category. This shall not be used directly.

CheckAndSetVariable

Set the variable in its category, verify lock, etc.. This shall not be used directly.

SetAttribute

        $config->SetAttribute(NAME => 'CC', VALUE => 'attribute') ;
        
        # or
        
        $config->Set(NAME => 'CC', VALUE => 'CC', ATTRIBUTE => 'attribute') ;
        
        my ($attribute, $attribute_exists) = $config->GetAttribute(NAME => 'CC') ;

This allows you to attach an attribute per variable (the attribute you set is per category) other than a value.

This sub will raise an exception if you try to set a variable that does not exists or if you try to set an attribute to a variable in an aliased category.

  • CATEGORY

    Let you specify in which category you want to find the variable you want to set the attribute of.

GetAttribute

        $config->SetAttribute(NAME => 'CC', VALUE => 'attribute') ;
        
        # or
        
        $config->Set(NAME => 'CC', VALUE => 'CC', ATTRIBUTE => 'attribute') ;
        
        my ($attribute, $attribute_exists) = $config->GetAttribute(NAME => 'CC') ;

A warning message is displayed if you call this sub in void or scalar context.

This sub returns the attribute as well as the existence of the attribute. If the attribute didn't exist, the value is set to undef. No warnings are displayed if you query the attribute of a variable that does not have an attribute.

This sub will raise an exception if you query a variable that does not exists.

Validate

This shall not be used directly.

Get

  my $config = new Config::Hierarchical(INITIAL_VALUES => [{NAME => 'CC', VALUE => 'gcc'}]) ;
  
  my $cc = $config->Get(NAME => 'CC') ;
  my $ld = $config->Get(NAME => 'LD', SILENT_NOT_EXISTS => 1) ;

Returns the value associated with the variable passed as argument. If more than one category contains the variable, the variable from the category with the highest priority, which is not overridden, will be used.

This function verifies its calling context and will generate a warning if it is called in void context.

If the variable doesn't exist in the container, a warning is displayed and undef is returned.

Options

  • SILENT_NOT_EXISTS

    Setting this option will disable the warning generated when the variable doesn't exist in the container.

  • CATEGORIES_TO_EXTRACT_FROM

    If set, Get will only search in the specified categories.

  • GET_CATEGORY

    If this option is set, Get will return the value _and_ the category it it comes from.

SetMultiple

  $config->SetMultiple
        (
        {FORCE_LOCK => 1},
        
        [NAME => 'CC', VALUE => 'gcc', SILENT_OVERRIDE => 1],
        [NAME => 'LD', VALUE => 'ld'],
        ) ;

If the first argument is a hash reference, the elements of the hash will be used for each element to set.

see Set.

GetMultiple

  my $config = new Config::Hierarchical(INITIAL_VALUES => [{NAME => 'CC', VALUE => 'gcc'}]) ;
  
  my @values = $config->GetMultiple('CC') ;
  
  my @other_values = $config->GetMultiple
                        (
                        {SILENT_NOT_EXISTS => 1},
                        'CC',
                        'AR'
                        ) ;

If the first argument is a hash reference, the elements of the hash will be used for each element to set.

Option GET_CATEGORY will be ignored in this sub.

see Get.

GetKeys

  my @keys = $config->GetKeys() ;

Returns the names of the element in the config object.

Options

  • CATEGORIES_TO_EXTRACT_FROM

    if set, GetKeyValueTuples will only search in the specified categories.

A warning will be generated if GetKeys is called in void context.

GetKeyValueTuples

        my $config_1 = new Config::Hierarchical(.....) ;
        
        my $config_2 = new Config::Hierarchical
                                        (
                                        NAME => 'config 2',
                                        
                                        CATEGORY_NAMES         => ['PARENT', 'CURRENT'],
                                        DEFAULT_CATEGORY       => 'CURRENT',
                                        
                                        INITIAL_VALUES =>
                                                [
                                                # Initializing a category from another config
                                                map
                                                        ({
                                                                {
                                                                NAME     => $_->{NAME},
                                                                VALUE    => $_->{VALUE}, 
                                                                CATEGORY => 'PARENT',
                                                                LOCK     => 1,
                                                                HISTORY  => $config_1->GetHistory(NAME => $_->{NAME}),
                                                                }
                                                        } $config_1->GetKeyValueTuples()),
                                                
                                                {NAME => 'CC', VALUE => 1,},
                                                ]
                                        ) ;

Returns a list of hash references containing the name and the value of each configuration variable contained in the object. This can be useful when you you create config objects from data in other objects.

Options

  • CATEGORIES_TO_EXTRACT_FROM

    If set, GetKeyValueTuples will only search in the specified categories.

GetHashRef

  my $hash_ref = $config->GetHashRef() ;

Returns a hash reference containing a copy of all the elements in the container. The elements value are extracted with the rules used in Get.

This function will generate an error if any argument is passed to it.

it will also generate a warning if:

it is called in void context
it is called in array context

SetDisplayExplicitCategoryWarningOption

  $config->SetDisplayExplicitCategoryWarningOption(1) ;
  $config->SetDisplayExplicitCategoryWarningOption(0) ;

When set, warning messages will be displayed if an explicit category is used in Get or Set.

SetDisableSilentOptions

  $config->SetDisableSilentOptions(1) ;
  $config->SetDisableSilentOptions(0) ;

When set, warning messages will be displayed regardless of local warning disabling options, i.e. SILENT_OVERRIDE and SILENT_NOT_EXIST.

This is useful when debugging your configuration as it forces all the warning to be displayed.

LockCategories

  $config->LockCategories('PARENT', 'OTHER') ;

Locks the categories passed as argument. A variable in a locked category can not be set. An attempt to set a locked variable will generate an error. FORCE_LOCK has no effect on locked categories.

An error is generated if you try to lock a category that doesn't exist.

See UnlockCategories.

Lock

  $config->Lock(NAME => 'CC') ;
  $config->Lock(NAME => 'CC', CATEGORY => 'PARENT') ;

Locks a variable in the default category or an explicit category. A locked variable can not be set. An attempt to set a locked variable will generate an error. To set a locked variable, FORCE_LOCK can be used. FORCE_LOCK usually pinpoints a problem in your configuration.

An error is generated if you try to lock a variable that doesn't exist.

See Set.

UnlockCategories

  $config->UnlockCategories('PARENT', 'OTHER') ;

Unlocks the categories passed as argument.

Unlock

  $config->Unlock(NAME => 'CC') ;
  $config->Unlock(NAME => 'CC', CATEGORY => 'PARENT') ;

See Lock.

IsCategoryLocked

  $config->IsCategoryLocked('PARENT') ;

Query the lock state of a category. Querying the lock state of a category that doesn't exist generates an error.

IsLocked

  $config->IsLocked(NAME => 'CC') ;
  $config->IsLocked(NAME => 'CC', CATEGORY => 'PARENT') ;

Query the lock state of a variable. Querying the lock state of a variable that doesn't exist does not generate an error.

Exists

  $config->Exists(NAME => 'CC') ;

Returns true if the variable exist, false otherwise. All the categories are checked.

GetHistory

  $history = $config->GetHistory(NAME => 'CC') ;
  $history = $config->GetHistory(NAME => 'CC', CATEGORIES_TO_EXTRACT_FROM => ['PARENT']) ;

Returns a reference to the variable's history or an empty list if the variable doesn't exist.

        my $config = new Config::Hierarchical
                                        (
                                        NAME => 'Test config',
                                        
                                        CATEGORY_NAMES         => ['PARENT', 'CURRENT'],
                                        DEFAULT_CATEGORY       => 'CURRENT',
                                                        
                                        INITIAL_VALUES  =>
                                                [
                                                {NAME => 'CC', CATEGORY => 'PARENT', VALUE => 'parent'},
                                                ] ,
                                        ) ;
                                        
        $config->Set(NAME => 'CC', OVERRIDE => 1, VALUE => 'override value') ;
        
        my($value, $category) = $config->Get(NAME => 'CC',  GET_CATEGORY => 1) ;
        
        my $title = "'CC' = '$value' from category '$category':" ;
        print DumpTree($config->GetHistory(NAME=> 'CC'), $title, DISPLAY_ADDRESS => 0) ;

Would print as:

        'CC' = 'override value' from category 'CURRENT':
        |- 0 
        |  |- EVENT = . CREATE AND SET. value = 'parent', category = 'PARENT' at 'nadim2.pl:21', status = OK. 
        |  `- TIME = 0 
        `- 1 
           |- EVENT = value = CREATE AND SET, OVERRIDE. 'override value', category = 'CURRENT' at 'nadim2.pl:34', status =
           |  Overriding 'PARENT::CC' (existed, value was different).OK. 
           `- TIME = 1 

while

        my($value, $category) = $config->Get(NAME => 'CC', GET_CATEGORY => 1, CATEGORIES_TO_EXTRACT_FROM => ['PARENT']) ;
        
        my $title = "'CC' = '$value' from category '$category':" ;
        print DumpTree($config->GetHistory(NAME=> 'CC', CATEGORIES_TO_EXTRACT_FROM => ['PARENT']), $title, DISPLAY_ADDRESS => 0) ;

Would print as:

        'CC' = 'parent' from category 'PARENT':
        `- 0 
           |- EVENT = value = CREATE AND SET. 'parent', category = 'PARENT' at 'nadim2.pl:21', status = OK. 
           `- TIME = 0 

Explicit history and comments

If you passed a HISTORY or a COMMENT when you created or modified a variable, that information will be included in the history structure returned by GetHistory.

        my $config3 = new Config::Hierarchical
                                        (
                                        NAME => 'config3',
                                        ...
                                        INITIAL_VALUES  =>
                                                [
                                                {
                                                COMMENT => "history and value from category 2", 
                                                NAME => 'CC', CATEGORY => 'PARENT', VALUE => $value2,
                                                HISTORY => $history2,
                                                },
                                                ] ,
                                        ...
                                        ) ;
                                        
        my($value3, $category3) = $config3->Get(NAME => 'CC',  GET_CATEGORY => 1) ;
        my $title3 = "'CC' = '$value3' from category '$category3':" ;
        my $history3 = $config3->GetHistory(NAME=> 'CC') ;
        print DumpTree($history3, $title3, DISPLAY_ADDRESS => 0) ;

Would print as:

        'CC' = '3' from category 'PARENT':
        |- 0
        |  |- COMMENT = history and value from config 2
        |  |- EVENT = CREATE, SET HISTORY AND SET. value = '3', category = 'PARENT' at 'history.pl:56', status = OK.
        |  |- HISTORY
        |  |  |- 0
        ...

Aliased category history

if you used an aliased category, The history structure returned by GetHistory will automatically include the history of the aliased config.

        my $config0 = (...) ;
        my $config1 = (...) ;
        my $config2 = new Config::Hierarchical
                                        (
                                        ...
                                        INITIAL_VALUES =>
                                                [
                                                {
                                                CATEGORY => 'PBS',
                                                ALIAS    => $pbs_config,
                                                HISTORY  => ....,
                                                COMMENT  => ....,
                                                },
                                        ...
                                        ) ;
                                        
        ...
        print DumpTree $config_3->GetHistory( NAME => 'CC1'), 'CC1', DISPLAY_ADDRESS => 0;

Would print as:

        CC1
        |- 0
        |  |- HISTORY FROM ALIASED CATEGORY 'config 1'
        |  |  |- 0
        |  |  |  |- HISTORY FROM ALIASED CATEGORY 'config 0'
        |  |  |  |  `- 0
        |  |  |  |     |- EVENT = CREATE AND SET. value = '1', category = 'CURRENT' at 'nadim.pl:21', status = OK.
        |  |  |  |     `- TIME = 0
        |  |  |  `- TIME = 2
        |  |  |- 1
        |  |  |  |- EVENT = CREATE AND SET. value = '1', category = 'A' at 'nadim.pl:33', status = OK.
        |  |  |  `- TIME = 3
        |  |  `- 2
        |  |     |- EVENT = Set. value = '1.1', category = 'A' at 'nadim.pl:50', status = OK.
        |  |     `- TIME = 6
        |  `- TIME = 3
        |- 1
        |  |- EVENT = CREATE AND SET, OVERRIDE. value = 'A', category = 'A' at 'nadim.pl:64', status = OK.
        |  `- TIME = 4
        `- 2
           |- EVENT = SET, OVERRIDE. value = 'A2', category = 'A' at 'nadim.pl:65', status = OK.
           `- TIME = 5

Compact display

Given the following Data::TreeDumper filter

        sub Compact
        {
        my ($s, $level, $path, $keys, $setup, $arg) = @_ ;
        
        if('ARRAY' eq ref $s)
                {
                my ($index, @replacement, @keys) = (0) ;
                
                for my $entry( @$s)
                        {
                        if(exists $entry->{EVENT})
                                {
                                push @replacement, $entry->{EVENT} ; #. 'time: ' . $entry->{TIME};
                                push@keys, $index++ ;
                                }
                        else
                                {
                                my ($aliased_history_name) = grep {$_ ne 'TIME'} keys %$entry ;
                                
                                push @replacement, $entry->{$aliased_history_name} ;
                                push@keys, [$index, "$index = $aliased_history_name"] ;
                                $index++ ;
                                }
                        }
                
                return('ARRAY', \@replacement, @keys) ;
                }
        }
        
        print DumpTree $config_2->GetHistory( NAME => 'CC1'), 'CC1', DISPLAY_ADDRESS => 0, FILTER => \&Compact ;

the above output becomes:

        CC1
        |- 0 = HISTORY FROM ALIASED CATEGORY 'config 1'
        |  |- 0 = HISTORY FROM ALIASED CATEGORY 'config 0'
        |  |  `- 0 = CREATE AND SET. value = '1', category = 'CURRENT' at 'nadim.pl:21', status = OK.
        |  |- 1 = CREATE AND SET. value =  '1', category = 'A' at 'nadim.pl:33', status = OK.
        |  `- 2 = SET. value = '1.1', category = 'A' at 'nadim.pl:50', status = OK.
        |- 1 = CREATE AND SET, OVERRIDE. value = 'A', category = 'A' at 'nadim.pl:64', status = OK.
        `- 2 = SET, OVERRIDE. value = 'A2', category = 'A' at 'nadim.pl:65', status = OK.

Note that comments are also removed.

GetVariableHistory

This shall not be used directly. Use GetHistory.

GetHistoryDump

  $dump = $config->GetHistoryDump(NAME => 'CC') ;
  
  $dump = $config->GetHistoryDump(CATEGORIES_TO_EXTRACT_FROM => ['A', 'B'], NAME => 'CC', DATA_TREEDUMPER_OPTIONS => []) ;

Returns a dump, of the variable history, generated by Data::TreeDumper::DumpTree.

See Data::TreeDumper.

GetDump

  $dump = $config->GetDump() ;
  $dump = $config->GetDump(@data_treedumper_options) ;

Returns a dump, of the Config::Hierarchical object, generated by Data::TreeDumper::DumpTree. The arguments are forwarded to the dumper.

See Data::TreeDumper.

BUGS AND LIMITATIONS

None so far.

AUTHOR

        Khemir Nadim ibn Hamouda
        CPAN ID: NKH
        mailto:nadim@khemir.net

LICENSE AND COPYRIGHT

Copyright 2006-2007 Khemir Nadim. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Config::Hierarchical

You can also look for information at:

SEE ALSO

Config::Hierarchical::Tie::ReadOnly

Config::Hierarchical::Delta