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::Model::Value - Strongly typed configuration value

SYNOPSIS

 my $model = Config::Model->new() ;
 $model ->create_config_class 
  (
   name => "SomeClass",
   element => [
     country  => { type =>       'leaf',
                   value_type => 'enum',
                   choice =>      [qw/France US/]
                 },
     president => { type =>        'leaf',
                    value_type => 'string',
                    warp => [ '- country', 
                             France => { default => 'Chirac' },
                             US     => { default => 'Bush' }]
                  },
     ]
  );

DESCRIPTION

This class provides a way to specify configuration value with the following properties:

  • Strongly typed scalar: the value can either be an enumerated type, a boolean, a number, an integer or a string

  • default parameter: a value can have a default value specified during the construction.

  • built-in default parameter: specifies the default value that is built in the application to be configured. This built-in default value will not written in the configuration files. Only the fetch_standard method will return the built-in default value. This may be used for audit purpose.

  • mandatory value: reading a mandatory value will raise an exception if the value is not specified and has no default value.

  • dynamic change of property: A slave value can be registered to another master value so that the properties of the slave value can change according to the value of the master value. For instance, paper size value can be 'letter' for country 'US' and 'A4' for country 'France'.

  • A reference to the Id of a hash of list element. In other word, the value is an enumerated type where the possible values (choice) is defined by the existing keys of a has element somewhere in the tree. See "Value Reference".

Constructor

Value object should not be created directly.

Value model declaration

A leaf element must be declared with the following parameters:

value_type

Either boolean, enum, integer, enum_integer, number, string. Mandatory. See "Value types".

default

Specify the default value (optional)

built_in

Specify a built in default value (optional)

compute

Will compute a value according to a formula and other values. By default a computed value cannot be set. See Config::Model::ValueComputer for computed value declaration.

convert => [uc | lc ]

When stored, the value will be converted to uppercase (uc) or lowercase (lc).

min

Specify the minimum value (optional, only for integer, number or enum_integer)

max

Specify the maximum value (optional, only for integer, number or enum_integer)

mandatory

Set to 1 if the configuration value must be set by the configuration user (default: 0)

choice

Array ref of the possible value of an enum. Example :

 choice => [ qw/foo bar/]
refer_to

See "Value reference".

warp

See section below: </"Warp: dynamic value configuration">.

help

You may provide detailed description on possible values of this tied scalar with a hash ref. Example:

 help => { oui => "French for 'yes'", non => "French for 'no'"}

Value types

This modules can check several value types:

boolean

Accepts values 1 or 0, yes or no, true or false. The value read back is always 1 or 0.

enum

Enum choices must be specified by the choice parameter.

integer

Enable positive or negative integer

enum_integer

enum_integer authorise the value to be an integer or a value specified by the choice parameter. This type is used to specify a value which can be an integer or be disabled.

number

The value can be a decimal number

string

Actually, no check is performed with this type.

Warp: dynamic value configuration

The Warp functionality enable a Value object to change its properties (i.e. default value or its type) dynamically according to the value of another Value object locate elsewhere in the configuration tree. (See Config::Model::WarpedThing for an explanation on warp mechanism).

For instance if you declare 2 Value element this way:

 $model ->create_config_class (
   name => "TV_config_class",
   element => [
     country => {
       type => 'leaf',
       value_type => 'enum', 
       choice => [qw/US Europe Japan/]
     },
     tv_standard => {
       type => 'leaf',
       value_type => 'enum',
       choice => [qw/PAL NTSC/]  
       warp => { follow => '- country', # this points to the warp master
                 rules => { US     => { default => 'NTSC' },
                            Europe => { default => 'PAL'  },
                            Japan  => { default => 'NTSC' } 
                          }
               }
       ],
     },
   ]
  );

Setting country element to US will mean that tv_standard has a default value set to NTSC by the warp mechanism.

Likewise, th warp mechanism enables you to dynamically change the possible values of an enum element:

 state => {
      type => 'leaf',
      value_type => 'enum', # example is admittedly silly
      warp => [ follow => '- country',
                rules => { US     => { choice => ['Kansas', 'Texas'   ]},
                           Europe => { choice => ['France', 'Espagna' ]},
                           Japan  => { choice => ['Honshu', 'Hokkaido' ]}
                         }
      ]
 }

Note that the state element is not available until country is set to a value.

Cascaded warping

Warping value can be cascaded: A can be warped by B which can be warped by C. But this feature should be avoided since it can lead to a model very hard to debug. Bear in mind that:

  • Warp loop are not detected and will end up in "deep recursion subroutine" failures.

  • If you declare "diamond" shaped warp dependencies, the results will depend on the order of the warp algorithm and can be unpredictable.

  • The keys declared in the warp rules (US, Europe and Japan in the example above) cannot be checked at start time against the warp master Value. So a wrong warp rule key will be silently ignored during start up and will fail at run time.

Value Reference

To set up an enumerated value where the possible choice depends on the key of a Config::Model::AnyId object, you must use the refer_to parameter.

This parameter implies that:

  • the first argument points to an array or hash element in the configuration tree using the path syntax (See "grab" in Config::Model::Node for details). This path is treated like a computaion formula. Hence it can contain variable and substitution like a computation formula.

  • The following arguments define the variable used in the path formula.

  • The value_type of the Value object with a refer_to parameter is forced to enum

  • The available choice of this enum is made from the available keys of the refered_to hash element or the range of the refered_to array element.

The example means the the value must correspond to an existing host:

 refer_to => '! host' 

This example means the the value must correspond to an existing lan within the host whose Id is specified by hostname:

 refer_to => ['! host:$a lan', a => '- hostname' ]

Value reference example

## FIXME: get an example...

Introspection methods

The following methods returns the current value of the Id object (as declared in the model unless they were warped):

min
max
mandatory
choice
convert
value_type
default
index_value
element_name

name()

Returns the object name.

get_type

Returns leaf.

can_store()

Returns true if the value object can be assigned to. Return 0 for a read-only value (i.e. a computed value with no override allowed).

get_choice()

Query legal values (only for enum types)

get_help ( [ on_value ] )

Returns the help strings passed to the constructor.

With on_value parameter, returns the help string dedicated to the passed value or undef.

Without parameter returns a hash ref that contains all the help strings.

Information management

store( value )

Store value in leaf element.

fetch_custom

Returns the stored value if this value is different from a standard setting. In other words, returns undef if the stored value is identical to the default value or the computed value.

fetch_standard

Returns the standard value as defined by the configuration model. The standard value can be either a computed value, a default value or a built-in default value.

fetch()

Fetch value from leaf element

user_value

Returns the value entered by the user. Does not use the default or computed value. Returns undef unless a value was actually stored.

EXCEPTION HANDLING

When an error is encountered, this module may throw the following exceptions:

 Config::Model::Exception::Model
 Config::Model::Exception::Formula
 Config::Model::Exception::WrongValue
 Config::Model::Exception::WarpError

See Config::Model::Exception for more details.

AUTHOR

Dominique Dumont, domi@komarr.grenoble.hp.com

SEE ALSO

Config::Model::AnyId, Config::Model::WarpThing, Exception::Class