NAME¶
Config::Model::Value - Strongly typed configuration value
VERSION¶
version 2.021
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',
description => 'foobar',
},
country => {
type => 'leaf',
value_type => 'enum',
choice => [qw/France US/],
description => 'big countries',
},
],
) ;
my $inst = $model->instance(root_class_name => 'MyClass' );
my $root = $inst->config_root ;
# put data
$root->load( step => 'foo=FOO country=US' );
print $root->report ;
# foo = FOO
# DESCRIPTION: foobar
#
# country = US
# DESCRIPTION: big countries
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. This default value will be written in
the target configuration file. ("default" parameter)
- •
- upstream default parameter: specifies a default value that
will be used by the application when no information is provided in the
configuration file. This upstream_default value will not written in the
configuration files. Only the "fetch_standard" method will
return the builtin value. This parameter was previously referred as
"built_in" value. This may be used for audit purpose.
("upstream_default" parameter)
- •
- 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".
Default values¶
There are several kind of default values. They depend on where these values are
defined (or found).
From the lowest default level to the "highest":
- •
- "upstream_default": The value is known in the
application, but is not written in the configuration file.
- •
- "layered": The value is known by the application
through another mean (e.g. an included configuration file), but is not
written in the configuration file.
- •
- "default": The value is known by the model, but
not by the application. This value must be written in the configuration
file.
- •
- "computed": The value is computed from other
configuration elements. This value must be written in the configuration
file.
- •
- "preset": The value is not known by the model or
by the application. But it can be found by an automatic program and stored
while the configuration Config::Model::Instance is in
Config::Model::Instance/"preset_start ()"
Then there is the value entered by the user. This will override all kind of
"default" value.
The fetch_standard function will return the "highest" level of default
value, but will not return a custom value, i.e. a value entered by the user.
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", "number", "uniline",
"string". Mandatory. See "Value types".
- default
- Specify the default value (optional)
- upstream_default
- Specify a built in default value (optional). I.e a value
known by the application which does not need to be written in the
configuration file.
- write_as
- Array ref. Reserved for boolean value. Specify how to write
a boolean value. Default is "[0,1]" which may not be the most
readable. "write_as" can be specified as
"['false','true']" or "['no','yes']".
- 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.
- migrate_from
- This is a special parameter to cater for smooth
configuration upgrade. This parameter can be used to copy the value of a
deprecated parameter to its replacement. See "upgrade"" in
" for details.
- 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)
- max
- Specify the maximum value (optional, only for integer,
number)
- 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/]
- match
- Perl regular expression. The value will be match with the
regex to assert its validity. Example "match => '^foo'" means
that the parameter value must begin with "foo". Valid only for
"string" or "uniline" values.
- warn_if_match
- Hash ref. Keys are made of Perl regular expression. The
value can specify a warning message (leave empty or undefined for default
warning message) and instructions to fix the value. A warning will be
issued when the value match the passed regular expression. Valid only for
"string" or "uniline" values. The fix instructions
will be evaluated when apply_fixes is called. $_ will contain the value to
fix. $_ will be stored as the new value once the instructions are done.
$self will contain the value object. Use with care.
In the example below, any value matching 'foo' will be converted in
uppercase:
warn_if_match => { 'foo' => { fix =>'uc;', msg => 'lower foo is not good'}},
- warn_unless_match
- Hash ref like above. A warning will be issued when the
value does not match the passed regular expression. Valid only for
"string" or "uniline" values.
- warn
- String. Issue a warning to user with the specified string
any time a value is set or read.
- warn_unless
- A bit like "warn_if_match". The hash key is not a
regexp but a label to help users. The hash ref contains some Perl code
that is evaluated to perform the test. A warning will be issued if the
code returns false.
$_ will contains the value to check. $self will contain the
"Config::Model::Value" object.
The example below will warn if a directory is missing:
warn_unless => { 'dir' => { code => '-d' , msg => 'missing dir', fix => "system(mkdir $_);" }}
- assert
- Like "warn_if_match". Except that returned value
will trigger an error if false.
- grammar
- Setup a Parse::RecDescent grammar to perform validation.
If the grammar does not start with a "check" rule (i.e does not
start with "check: "), the first line of the grammar will be
modified to add "check" rule and set up this rules so the entire
value must match the passed grammar.
I.e. the grammar:
token (oper token)(s?)
oper: 'and' | 'or'
token: 'Apache' | 'CC-BY' | 'Perl'
will be changed to
check: token (oper token)(s?) /^\Z/ {$return = 1;}
oper: 'and' | 'or'
token: 'Apache' | 'CC-BY' | 'Perl'
The rule is called with Value object and a string reference. So, in the
actions you may need to define, you can call the value object as $arg[0],
store error message in "${$arg[1]}}" and store warnings in
"${$arg[2]}}".
- replace
- Hash ref. Used for enum to substitute one value with
another. This parameter must be used to enable user to upgrade a
configuration with obsolete values. For instance, if the value
"foo" is obsolete and replaced by "foo_better", you
will need to declare:
replace => { foo => 'foo_better' }
The hash key can also be a regular expression for wider range replacement.
The regexp must match the whole value:
replace => ( 'foo.*' => 'better_foo' }
In this case, a value will be replaced by "better_foo" if the
"/^foo.*$/" regexp matches.
- replace_follow
- Path specifying a hash of value element in the
configuration tree. The hash if used in a way similar to the
"replace" parameter. In this case, the replacement is not coded
in the model but specified by the configuration.
- refer_to
- Specify a path to an id element used as a reference. See
Value Reference for details.
- computed_refer_to
- Specify a path to an id element used as a computed
reference. See "Value Reference" for details.
- warp
- See section below: "Warp: dynamic value
configuration".
- help
- You may provide detailed description on possible values
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
- "number"
- The value can be a decimal number
- "uniline"
- A one line string. I.e without "\n" in it.
- "string"
- Actually, no check is performed with this type.
- "reference"
- Like an "enum" where the possible values (aka
choice) is defined by another location if the configuration tree. See
"Value Reference".
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 SECAM/]
warp => {
follow => { c => '- country' }, # this points to the warp master
rules => {
'$c eq "US"' => { default => 'NTSC' },
'$c eq "France"' => { default => 'SECAM' },
'$c eq "Japan"' => { default => 'NTSC' },
'$c eq "Europe"' => { default => 'PAL' },
}
}
},
]
);
Setting "country" element to "US" will mean that
"tv_standard" has a default value set to "NTSC" by the
warp mechanism.
Likewise, the 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 => { c => '- country' },
rules => {
'$c eq "US"' => { choice => ['Kansas', 'Texas' ]},
'$c eq "Europe"' => { choice => ['France', 'Spain' ]},
'$c eq "Japan"' => { choice => ['Honshu', 'Hokkaido' ]}
}
}
}
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:
- •
- Set "value_type" to "reference".
- •
- Specify the "refer_to" or
"computed_refer_to" parameter. See refer_to parameter.
In this case, a "IdElementReference" object is created to handle the
relation between this value object and the referred Id. See
Config::Model::IdElementReference for details.
Introspection methods¶
The following methods returns the current value of the parameter of the value
object (as declared in the model unless they were warped):
- min
- max
- mandatory
- choice
- convert
- value_type
- default
- upstream_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). Return an array (possibly empty).
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.
error_msg¶
Returns the error messages of this object (if any)
warning_msg¶
Returns warning concerning this value. Returns a list in list context and a
string in scalar context.
check_value ( value )¶
Check the consistency of the value.
"check_value" also accepts named parameters:
- value
- quiet
- When non null, check will not try to get extra information
from the tree. This is required in some cases to avoid loops in check,
get_info, get_warp_info, re-check ...
In scalar context, return 0 or 1.
In array context, return an empty array when no error was found. In case of
errors, returns an array of error strings that should be shown to the user.
has_fixes¶
Returns the number of fixes that can be applied to the current value.
apply_fixes¶
Applies the fixes to suppress the current warnings.
check( [ value => foo ] )¶
Like "check_value".
Will also display warnings on STDOUT unless "silent" parameter is set
to 1. In this case,user is expected to retrieve them with warning_msg.
Without "value" argument, this method will check the value currently
stored.
store( value )¶
Can be called as "value => ..., check => yes|no|skip )"
Store value in leaf element. "check" parameter can be used to skip
validation check.
load_data( scalar_value )¶
Load scalar data. Data is simply forwarded to store.
fetch_custom¶
Returns the stored value if this value is different from a standard setting or
built in setting. In other words, returns undef if the stored value is
identical to the default value or the computed value or the built in value.
fetch_standard¶
Returns the standard value as defined by the configuration model. The standard
value can be either a preset value, a layered value, a computed value, a
default value or a built-in default value.
fetch( ... )¶
Check and fetch value from leaf element. The method can have one parameter (the
fetch mode) or several pairs:
- mode
- Whether to fetch default, custom, etc value. See below for
details
- check
- Whether to check if the value is valid or not before
returning it. Default is 'yes'. Possible value are
- yes
- Perform check and raise an exception for bad values
- skip
- Perform check and return undef for bad values
- no
- Do not check and return values even if bad
- silent
- When set to 1, warning are not displayed on STDOUT. User is
expected to read warnings with warning_msg method.
According to the "mode" parameter, this method will return either:
- empty mode parameter (default)
- Value entered by user or default value if the value is
different from upstream_default or layered value. Typically this value
will be written in a configuration file.
- backend
- Alias for default mode.
- custom
- The value entered by the user (if different from built in,
preset, computed or default value)
- user
- The value most useful to user: the value that will be used
by the application.
- preset
- The value entered in preset mode
- standard
- The preset or computed or default or built in value.
- default
- The default value (defined by the configuration model)
- layered
- The value found in included files (treated in layered mode:
values specified there are handled as upstream default values). E.g. like
in multistrap config.
- upstream_default
- The upstream_default value. (defined by the configuration
model)
- non_upstream_default
- The custom or preset or computed or default value. Will
return undef if either of this value is identical to the upstream_default
value. This feature is useful to reduce data to write in configuration
file.
- allow_undef
- This mode will accept to return undef for mandatory values.
Normally, trying to fetch an undefined mandatory value leads to an
exception.
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.
fetch_preset¶
Returns the value entered in preset mode. Does not use the default or computed
value. Returns undef unless a value was actually stored in preset mode.
clear_preset¶
Delete the preset value. (Even out of preset mode). Returns true if other data
are still stored in the value (layered or user data). Returns false otherwise.
fetch_layered¶
Returns the value entered in layered mode. Does not use the default or computed
value. Returns undef unless a value was actually stored in layered mode.
clear_layered¶
Delete the layered value. (Even out of layered mode). Returns true if other data
are still stored in the value (layered or user data). Returns false otherwise.
get( path => ..., mode => ... , check => ... )¶
Get a value from a directory like path.
set( path , value )¶
Set a value from a directory like path.
Examples¶
Number with min and max values¶
bounded_number => {
type => 'leaf',
value_type => 'number',
min => 1,
max => 4,
},
Mandatory value¶
mandatory_string => {
type => 'leaf',
value_type => 'string',
mandatory => 1,
},
mandatory_boolean => {
type => 'leaf',
value_type => 'boolean',
},
Enum with help associated with each value¶
Note that the help specification is optional.
enum_with_help => {
type => 'leaf',
value_type => 'enum',
choice => [qw/a b c/],
help => { a => 'a help' }
},
Migrate old obsolete enum value¶
Legacy values "a1", "c1" and "foo/.*" are replaced
with "a", "c" and "foo/".
with_replace => {
type => 'leaf',
value_type => 'enum',
choice => [qw/a b c/],
replace => {
a1 => 'a',
c1 => 'c',
'foo/.*' => 'foo',
},
},
Enforce value to match a regexp¶
An exception will be triggered if the value does not match the "match"
regular expression.
match => {
type => 'leaf',
value_type => 'string',
match => '^foo\d{2}$',
},
Enforce value to match a Parse::RecDescent grammar¶
prd_match => {
type => 'leaf',
value_type => 'string',
grammar => q{
token (oper token)(s?)
oper: 'and' | 'or'
token: 'Apache' | 'CC-BY' | 'Perl'
},
},
Issue a warning if a value matches a regexp¶
Issue a warning if the string contains upper case letters. Propose a fix that
translate all capital letters to lower case.
warn_if_capital => {
type => 'leaf',
value_type => 'string',
warn_if_match => { '/A-Z/' => { fix => '$_ = lc;' } },
},
A specific warning can be specified:
warn_if_capital => {
type => 'leaf',
value_type => 'string',
warn_if_match => {
'/A-Z/' => {
fix => '$_ = lc;' ,
mesg =>'NO UPPER CASE PLEASE'
}
},
},
Issue a warning if a value does NOT match a regexp¶
warn_unless => {
type => 'leaf',
value_type => 'string',
warn_unless_match => { foo => { msg => '', fix => '$_ = "foo".$_;' } },
},
Always issue a warning¶
always_warn => {
type => 'leaf',
value_type => 'string',
warn => 'Always warn whenever used',
},
Computed values¶
See "Examples" in Config::Model::ValueComputer.
Upgrade¶
Upgrade is a special case when the configuration of an application has changed.
Some parameters can be removed and replaced by another one. To avoid trouble
on the application user side, Config::Model offers a possibility to handle the
migration of configuration data through a special declaration in the
configuration model.
This declaration must:
- •
- Declare the deprecated parameter with a "status"
set to "deprecated"
- •
- Declare the new parameter with the instructions to load the
semantic content from the deprecated parameter. These instructions are
declared in the "migrate_from" parameters (which is similar to
the "compute" parameter)
Here an example where a URL parameter is changed to a set of 2 parameters (host
and path):
'old_url' => { type => 'leaf',
value_type => 'uniline',
status => 'deprecated',
},
'host'
=> { type => 'leaf',
value_type => 'uniline',
# the formula must end with '$1' so the result of the capture is used
# as the host value
migrate_from => { formula => '$old =~ m!http://([\w\.]+)!; $1 ;' ,
variables => { old => '- old_url' } ,
use_eval => 1 ,
},
},
'path' => { type => 'leaf',
value_type => 'uniline',
migrate_from => { formula => '$old =~ m!http://[\w\.]+(/.*)!; $1 ;',
variables => { old => '- old_url' } ,
use_eval => 1 ,
},
},
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, (ddumont at cpan dot org)
SEE ALSO¶
Config::Model, Config::Model::Node, Config::Model::AnyId,
Config::Model::WarpedThing, Exception::Class
Config::Model::ValueComputer,