File Coverage

blib/lib/Config/Model/Value.pm
Criterion Covered Total %
statement 871 944 92.2
branch 450 558 80.6
condition 278 365 76.1
subroutine 109 118 92.3
pod 29 64 45.3
total 1737 2049 84.7


line stmt bran cond sub pod time code
1             #
2             # This file is part of Config-Model
3             #
4             # This software is Copyright (c) 2005-2022 by Dominique Dumont.
5             #
6             # This is free software, licensed under:
7             #
8             # The GNU Lesser General Public License, Version 2.1, February 1999
9             #
10             package Config::Model::Value 2.153; # TRIAL
11              
12 59     59   945 use v5.20;
  59         243  
13              
14 59     59   391 use strict;
  59         146  
  59         1392  
15 59     59   296 use warnings;
  59         148  
  59         3278  
16 59     59   402 use feature "switch";
  59         157  
  59         7040  
17              
18 59     59   503 use Mouse;
  59         1410  
  59         653  
19 59     59   28844 use Mouse::Util::TypeConstraints;
  59         164  
  59         496  
20 59     59   6993 use MouseX::StrictConstructor;
  59         170  
  59         535  
21              
22 59     59   89432 use Parse::RecDescent 1.90.0;
  59         2586783  
  59         406  
23              
24 59     59   3621 use Data::Dumper ();
  59         163  
  59         1143  
25 59     59   362 use Config::Model::Exception;
  59         160  
  59         2744  
26 59     59   39702 use Config::Model::ValueComputer;
  59         219  
  59         2158  
27 59     59   29982 use Config::Model::IdElementReference;
  59         196  
  59         2209  
28 59     59   33713 use Config::Model::Warper;
  59         226  
  59         2521  
29 59     59   470 use Log::Log4perl qw(get_logger :levels);
  59         126  
  59         419  
30 59     59   8546 use Scalar::Util qw/weaken/;
  59         151  
  59         3226  
31 59     59   385 use Carp;
  59         133  
  59         3314  
32 59     59   395 use Storable qw/dclone/;
  59         256  
  59         2699  
33 59     59   453 use Path::Tiny;
  59         155  
  59         3793  
34 59     59   479 use List::Util qw(any) ;
  59         166  
  59         7496  
35             extends qw/Config::Model::AnyThing/;
36              
37             with "Config::Model::Role::WarpMaster";
38             with "Config::Model::Role::Grab";
39             with "Config::Model::Role::HelpAsText";
40             with "Config::Model::Role::ComputeFunction";
41              
42 59     59   480 use feature qw/postderef signatures/;
  59         132  
  59         3774  
43 59     59   433 no warnings qw/experimental::postderef experimental::smartmatch experimental::signatures/;
  59         218  
  59         539590  
44              
45             my $logger = get_logger("Tree::Element::Value");
46             my $user_logger = get_logger("User");
47             my $change_logger = get_logger("Anything::Change");
48             my $fix_logger = get_logger("Anything::Fix");
49              
50             our $nowarning = 0; # global variable to silence warnings. Only used for tests
51              
52             enum ValueType => qw/boolean enum uniline string integer number reference file dir/;
53              
54             has fixes => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
55              
56             has [qw/warp compute computed_refer_to backup migrate_from/] =>
57             ( is => 'rw', isa => 'Maybe[HashRef]' );
58              
59             has compute_obj => (
60             is => 'ro',
61             isa => 'Maybe[Config::Model::ValueComputer]',
62             builder => '_build_compute_obj',
63             lazy => 1
64             );
65              
66             has [qw/write_as/] => ( is => 'rw', isa => 'Maybe[ArrayRef]' );
67              
68             has [qw/refer_to _data replace_follow/] => ( is => 'rw', isa => 'Maybe[Str]' );
69              
70             has value_type => ( is => 'rw', isa => 'ValueType' );
71              
72             my @common_int_params = qw/min max mandatory /;
73             has \@common_int_params => ( is => 'ro', isa => 'Maybe[Int]' );
74              
75             my @common_hash_params = qw/replace assert warn_if_match warn_unless_match warn_if warn_unless help/;
76             has \@common_hash_params => ( is => 'ro', isa => 'Maybe[HashRef]' );
77              
78             my @common_list_params = qw/choice/;
79             has \@common_list_params => ( is => 'ro', isa => 'Maybe[ArrayRef]' );
80              
81             my @common_str_params = qw/default upstream_default convert match grammar warn/;
82             has \@common_str_params => ( is => 'ro', isa => 'Maybe[Str]' );
83              
84             my @warp_accessible_params =
85             ( @common_int_params, @common_str_params, @common_list_params, @common_hash_params );
86              
87             my @allowed_warp_params = ( @warp_accessible_params, qw/level help/ );
88             my @backup_list = ( @allowed_warp_params, qw/migrate_from/ );
89              
90             has compute_is_upstream_default =>
91             ( is => 'ro', isa => 'Bool', lazy => 1, builder => '_compute_is_upstream_default' );
92              
93             sub _compute_is_upstream_default {
94 2777     2777   4609 my $self = shift;
95 2777 100       12947 return 0 unless defined $self->compute;
96 44         283 return $self->compute_obj->use_as_upstream_default;
97             }
98              
99             has compute_is_default =>
100             ( is => 'ro', isa => 'Bool', lazy => 1, builder => '_compute_is_default' );
101              
102             sub _compute_is_default {
103 3148     3148   6090 my $self = shift;
104 3148 100       17149 return 0 unless defined $self->compute;
105 45         199 return !$self->compute_obj->use_as_upstream_default;
106             }
107              
108             has error_list => (
109             is => 'ro',
110             isa => 'ArrayRef',
111             default => sub { [] },
112             traits => ['Array'],
113             handles => {
114             add_error => 'push',
115             clear_errors => 'clear',
116             has_error => 'count',
117             all_errors => 'elements',
118             is_ok => 'is_empty'
119             } );
120              
121 44     44 1 908 sub error_msg ($self) {
  44         82  
  44         85  
122 44         92 my $msg = '';
123 44 100       127 if ($self->has_error) {
124 43         342 my @add;
125 43 100       217 push @add, $self->compute_obj->compute_info if $self->compute_obj;
126 43 50       191 push @add, $self->{_migrate_from}->compute_info if $self->{_migrate_from};
127 43         156 $msg = join("\n", $self->all_errors, @add);
128             }
129 44         1086 return $msg;
130             }
131              
132             has warning_list => (
133             is => 'ro',
134             isa => 'ArrayRef',
135             default => sub { [] },
136             traits => ['Array'],
137             handles => {
138             add_warning => 'push',
139             clear_warnings => 'clear',
140             warning_msg => [ join => "\n\t" ],
141             has_warning => 'count',
142             has_warnings => 'count',
143             all_warnings => 'elements',
144             } );
145              
146             # as some information must be backed up even though they are not
147             # attributes, we cannot move code below in BUILD.
148             around BUILDARGS => sub ($orig, $class, %args) {
149             my %h = map { ( $_ => $args{$_} ); } grep { defined $args{$_} } @backup_list;
150             return $class->$orig( backup => dclone( \%h ), %args );
151             };
152              
153             sub BUILD {
154 3487     3487 1 6419 my $self = shift;
155              
156 3487         10002 $self->set_properties(); # set will use backup data
157              
158             # used when self is a warped slave
159 3485 100       12077 if ( my $warp_info = $self->warp ) {
160 300         5244 $self->{warper} = Config::Model::Warper->new(
161             warped_object => $self,
162             %$warp_info,
163             allowed => \@allowed_warp_params
164             );
165             }
166              
167 3484         10342 $self->_init;
168              
169 3482         23739 return $self;
170             }
171              
172             override 'needs_check' => sub ($self, @args) {
173             if ($self->instance->layered) {
174             # don't check value and don't store value in layered mode
175             return 0;
176             }
177             elsif (@args) {
178             return super();
179             }
180             else {
181             # some items like idElementReference are too complex to propagate
182             # a change notification back to the value using them. So an error or
183             # warning must always be rechecked.
184             return ($self->value_type eq 'reference' or super()) ;
185             }
186             };
187              
188             around notify_change => sub ($orig, $self, %args) {
189             my $check_done = $args{check_done} || 0;
190              
191             return if $self->instance->initial_load and not $args{really};
192              
193             if ($change_logger->is_trace) {
194             my @a = map { ( $_ => $args{$_} // '<undef>' ); } sort keys %args;
195             $change_logger->trace( "called while needs_check is ",
196             $self->needs_check, " for ", $self->name, " with ", join( ' ', @a ) );
197             }
198              
199             $self->needs_check(1) unless $check_done;
200             {
201             croak "needless change with $args{new}"
202             if defined $args{old}
203             and defined $args{new}
204             and $args{old} eq $args{new};
205             }
206             $args{new} = $self->map_write_as( $args{new} );
207             $args{old} = $self->map_write_as( $args{old} );
208             $self->$orig( %args, value_type => $self->value_type );
209              
210             # shake all warped or computed objects that depends on me
211             foreach my $s ( $self->get_depend_slave ) {
212             $change_logger->debug( "calling needs_check on slave ", $s->name )
213             if $change_logger->is_debug;
214             $s->needs_check(1);
215             }
216             return;
217             };
218              
219             # internal method
220             sub set_default {
221 4033     4033 0 7634 my ( $self, $arg_ref ) = @_;
222              
223 4033 50       9164 if ( exists $arg_ref->{built_in} ) {
224 0         0 $arg_ref->{upstream_default} = delete $arg_ref->{built_in};
225 0         0 warn $self->name, " warning: deprecated built_in parameter, ", "use upstream_default\n";
226             }
227              
228 4033 50 66     11003 if ( defined $arg_ref->{default} and defined $arg_ref->{upstream_default} ) {
229 0         0 Config::Model::Exception::Model->throw(
230             object => $self,
231             error => "Cannot specify both 'upstream_default' and " . "'default' parameters",
232             );
233             }
234              
235 4033         7297 foreach my $item (qw/upstream_default default/) {
236 8066         13124 my $def = delete $arg_ref->{$item};
237              
238 8066 100       16927 next unless defined $def;
239 648 100       2527 $self->transform_boolean( \$def ) if $self->value_type eq 'boolean';
240              
241             # will check default value
242 648         1926 $self->check_value( value => $def );
243 648 100       2042 Config::Model::Exception::Model->throw(
244             object => $self,
245             error => "Wrong $item value\n\t" . $self->error_msg
246             ) if $self->has_error;
247              
248 646         6372 $logger->debug( "Set $item value for ", $self->name, "" );
249              
250 646         5484 $self->{$item} = $def;
251             }
252 4031         6140 return;
253             }
254              
255             # set up relation between objects required by the compute constructor
256             # parameters
257             sub _build_compute_obj {
258 1664     1664   3193 my $self = shift;
259              
260 1664         4967 $logger->trace("called");
261              
262 1664         14701 my $c_info = $self->compute;
263 1664 100       8975 return unless $c_info;
264              
265 45         70 my @compute_data;
266 45         185 foreach ( keys %$c_info ) {
267 98 50       331 push @compute_data, $_, $c_info->{$_} if defined $c_info->{$_};
268             }
269              
270             my $ret = Config::Model::ValueComputer->new(
271             @compute_data,
272             value_object => $self,
273             value_type => $self->{value_type},
274 45         870 );
275              
276             # resolve any recursive variables before registration
277 45         242 my $v = $ret->compute_variables;
278              
279 45         187 $self->register_in_other_value($v);
280 44         129 $logger->trace("done");
281 44         906 return $ret;
282             }
283              
284             sub register_in_other_value {
285 49     49 0 105 my $self = shift;
286 49         100 my $var = shift;
287              
288             # register compute or refer_to dependency. This info may be used
289             # by other tools
290 49         129 foreach my $path ( values %$var ) {
291 45 100 66     215 if ( defined $path and not ref $path ) {
292              
293             # is ref during test case
294             #print "path is '$path'\n";
295 43 50       147 next if $path =~ /\$/; # next if path also contain a variable
296 43         145 my $master = $self->grab($path);
297 42 50       255 next unless $master->can('register_dependency');
298 42         148 $master->register_dependency($self);
299             }
300             }
301 48         95 return;
302             }
303              
304             # internal
305             sub perform_compute {
306 107     107 0 1929 my $self = shift;
307 107         303 $logger->trace("called");
308              
309 107         1115 my $result = $self->compute_obj->compute;
310              
311             # check if the computed result fits with the constraints of the
312             # Value model, but don't check if it's mandatory
313 107         381 my ($value, $error, $warn) = $self->_check_value(value => $result);
314              
315 107 100       331 if ( scalar $error->@* ) {
316 3         9 my $error = join("\n", (@$error, $self->compute_info));
317              
318 3         30 Config::Model::Exception::WrongValue->throw(
319             object => $self,
320             error => "computed value error:\n\t" . $error
321             );
322             }
323              
324 104         310 $logger->trace("done");
325 104         967 return $result;
326             }
327              
328             # internal, used to generate error messages
329             sub compute_info {
330 3     3 0 7 my $self = shift;
331 3         11 return $self->compute_obj->compute_info;
332             }
333              
334             sub set_migrate_from {
335 13     13 0 46 my ( $self, $arg_ref ) = @_;
336              
337 13         38 my $mig_ref = delete $arg_ref->{migrate_from};
338              
339 13 50       53 if ( ref($mig_ref) eq 'HASH' ) {
340 13         62 $self->migrate_from($mig_ref);
341             }
342             else {
343 0         0 Config::Model::Exception::Model->throw(
344             object => $self,
345             error => "migrate_from value must be a hash ref not $mig_ref"
346             );
347             }
348              
349 13         33 my @migrate_data;
350 13         44 foreach (qw/formula variables replace use_eval undef_is/) {
351 65 100       189 push @migrate_data, $_, $mig_ref->{$_} if defined $mig_ref->{$_};
352             }
353              
354             $self->{_migrate_from} = Config::Model::ValueComputer->new(
355             @migrate_data,
356             value_object => $self,
357 13         297 value_type => $self->{value_type} );
358              
359             # resolve any recursive variables before registration
360 13         87 my $v = $self->{_migrate_from}->compute_variables;
361 13         55 return;
362             }
363              
364             # FIXME: should it be used only once ???
365             sub migrate_value {
366 29     29 0 58 my $self = shift;
367              
368             # migrate value is always used as a scalar, even in list
369             # context. Not returning undef would break a hash assignment done
370             # with something like:
371             # my %args = (value => $obj->migrate_value, fix => 1).
372              
373             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
374              
375 29 100       100 return undef if $self->{migration_done};
376 19 100       101 return undef if $self->instance->initial_load;
377 13         45 $self->{migration_done} = 1;
378              
379             # avoid warning when reading deprecated values
380 13         60 my $result = $self->{_migrate_from}->compute( check => 'skip' );
381              
382 13 100       52 return undef unless defined $result;
383              
384             # check if the migrated result fits with the constraints of the
385             # Value object
386 7         24 my $ok = $self->check_value( value => $result );
387              
388             #print "check result: $ok\n";
389 7 50       32 if ( not $ok ) {
390 0         0 Config::Model::Exception::WrongValue->throw(
391             object => $self,
392             error => "migrated value error:\n\t" . $self->error_msg
393             );
394             }
395              
396             # old value is always undef when this method is called
397 7 50       38 $self->notify_change( note => 'migrated value', new => $result )
398             if length($result); # skip empty value (i.e. '')
399 7         22 $self->{data} = $result;
400              
401 7 50       28 return $ok ? $result : undef;
402             }
403              
404 1091     1091 0 2038 sub setup_enum_choice ($self, @args) {
  1091         1601  
  1091         1810  
  1091         1540  
405 1091 100       2732 my @choice = ref $args[0] ? @{ $args[0] } : @args;
  878         2867  
406              
407 1091         2757 $logger->debug( $self->name, " setup_enum_choice with '", join( "','", @choice ), "'" );
408              
409 1091         9885 $self->{choice} = \@choice;
410              
411             # store all enum values in a hash. This way, checking
412             # whether a value is present in the enum set is easier
413 1091 100       3266 delete $self->{choice_hash} if defined $self->{choice_hash};
414              
415 1091         2232 for ( @choice ) { $self->{choice_hash}{$_} = 1; }
  3643         7450  
416              
417             # delete the current value if it does not fit in the new
418             # choice
419 1091         2294 for ( qw/data preset/ ) {
420 2182         3601 my $lv = $self->{$_};
421 2182 100 100     5565 if ( defined $lv and not defined $self->{choice_hash}{$lv} ) {
422 6         58 delete $self->{$_};
423             }
424             }
425 1091         2650 return;
426             }
427              
428             sub setup_match_regexp {
429 29     29 0 63 my ( $self, $what, $ref ) = @_;
430              
431 29         89 my $str = $self->{$what} = delete $ref->{$what};
432 29 50       75 return unless defined $str;
433 29         49 my $vt = $self->{value_type};
434              
435 29 50 66     131 if ( $vt ne 'uniline' and $vt ne 'string' and $vt ne 'enum') {
      33        
436 0         0 Config::Model::Exception::Model->throw(
437             object => $self,
438             error => "Can't use $what regexp with $vt, expected 'enum', 'uniline' or 'string'"
439             );
440             }
441              
442 29         80 $logger->debug( $self->name, " setup $what regexp with '$str'" );
443 29         270 $self->{ $what . '_regexp' } = eval { qr/$str/; };
  29         244  
444              
445 29 50       77 if ($@) {
446 0         0 Config::Model::Exception::Model->throw(
447             object => $self,
448             error => "Unvalid $what regexp for '$str': $@"
449             );
450             }
451 29         57 return;
452             }
453              
454             sub check_validation_regexp {
455 26     26 0 65 my ( $self, $what, $ref ) = @_;
456              
457 26         66 my $regexp_info = delete $ref->{$what};
458 26 50       78 return unless defined $regexp_info;
459              
460 26         57 $self->{$what} = $regexp_info;
461              
462 26         50 my $vt = $self->{value_type};
463              
464 26 50 66     107 if ( $vt ne 'uniline' and $vt ne 'string' and $vt ne 'enum') {
      33        
465 0         0 Config::Model::Exception::Model->throw(
466             object => $self,
467             error => "Can't use $what regexp with $vt, expected 'enum', 'uniline' or 'string'"
468             );
469             }
470              
471 26 50 33     87 if ( not ref $regexp_info and $what ne 'warn' ) {
472 0         0 warn $self->name, ": deprecated $what style. Use a hash ref\n";
473             }
474              
475 26 50       66 my $h = ref $regexp_info ? $regexp_info : { $regexp_info => '' };
476              
477             # just check the regexp. values are checked later in &check_value
478 26         83 foreach my $regexp ( keys %$h ) {
479 29         74 $logger->debug( $self->name, " hash $what regexp with '$regexp'" );
480 29         339 eval { qr/$regexp/; };
  29         423  
481              
482 29 50       112 if ($@) {
483 0         0 Config::Model::Exception::Model->throw(
484             object => $self,
485             error => "Unvalid $what regexp '$regexp': $@"
486             );
487             }
488              
489 29         67 my $v = $h->{$regexp};
490 29 50       101 Config::Model::Exception::Model->throw(
491             object => $self,
492             error => "value of $what regexp '$regexp' is not a hash ref but '$v'"
493             ) unless ref $v eq 'HASH';
494              
495             }
496 26         66 return;
497             }
498              
499             sub setup_grammar_check {
500 1     1 0 4 my ( $self, $ref ) = @_;
501              
502 1         7 my $str = $self->{grammar} = delete $ref->{grammar};
503 1 50       4 return unless defined $str;
504 1         2 my $vt = $self->{value_type};
505              
506 1 50 33     9 if ( $vt ne 'uniline' and $vt ne 'string' ) {
507 0         0 Config::Model::Exception::Model->throw(
508             object => $self,
509             error => "Can't use match regexp with $vt, " . "expected 'uniline' or 'string'"
510             );
511             }
512              
513 1         11 my @lines = split /\n/, $str;
514 1         8 chomp @lines;
515 1 50       14 if ( $lines[0] !~ /^check:/ ) {
516 0         0 $lines[0] = 'check: ' . $lines[0] . ' /\s*\Z/ ';
517             }
518              
519 1         8 my $actual_grammar = join( "\n", @lines ) . "\n";
520 1         5 $logger->debug( $self->name, " setup_grammar_check with '$actual_grammar'" );
521 1         10 eval { $self->{validation_parser} = Parse::RecDescent->new($actual_grammar); };
  1         14  
522              
523 1 50       17759 if ($@) {
524 0         0 Config::Model::Exception::Model->throw(
525             object => $self,
526             error => "Unvalid grammar for '$str': $@"
527             );
528             }
529 1         4 return;
530             }
531              
532             # warning : call to 'set' are not cumulative. Default value are always
533             # restored. Lest keeping track of what was modified with 'set' is
534             # too confusing.
535 4034     4034 0 5804 sub set_properties ($self, @args) {
  4034         5757  
  4034         5842  
  4034         5362  
536             # cleanup all parameters that are handled by warp
537 4034         9068 for ( @allowed_warp_params ) { delete $self->{$_} }
  76646         110608  
538              
539             # merge data passed to the constructor with data passed to set_properties
540 4034   100     5877 my %args = ( %{ $self->backup // {} }, @args );
  4034         20896  
541              
542             # these are handled by Node or Warper
543 4034         8932 for ( qw/level/ ) { delete $args{$_} }
  4034         7442  
544              
545 4034 100       12557 if ( $logger->is_trace ) {
546 134         723 $logger->trace( "Leaf '" . $self->name . "' set_properties called with '",
547             join( "','", sort keys %args ), "'" );
548             }
549              
550 4034 0 33     32019 if ( defined $args{value_type}
      33        
      0        
551             and $args{value_type} eq 'reference'
552             and not defined $self->{refer_to}
553             and not defined $self->{computed_refer_to} ) {
554 0         0 Config::Model::Exception::Model->throw(
555             object => $self,
556             error => "Missing 'refer_to' or 'computed_refer_to' "
557             . "parameter with 'reference' value_type "
558             );
559             }
560              
561 4034         7492 for (qw/min max mandatory warn replace_follow assert warn_if warn_unless
562             write_as/) {
563 36306 100       66198 $self->{$_} = delete $args{$_} if defined $args{$_};
564             }
565              
566 4034 100       8983 if ($args{replace}) {
567 6         20 $self->{replace} = delete $args{replace};
568 6         18 my $old = $self->_fetch_no_check;
569 6 100       24 if (defined $old) {
570 3         12 my $new = $self->apply_replace($old);
571 3         8 $self->_store_value($new);
572             }
573             }
574              
575 4034         11415 $self->set_help( \%args );
576 4034         11306 $self->set_value_type( \%args );
577 4033         12056 $self->set_default( \%args );
578 4031 100       8824 $self->set_convert( \%args ) if defined $args{convert};
579 4031 100       8350 $self->setup_match_regexp( match => \%args ) if defined $args{match};
580 4031         6937 foreach (qw/warn_if_match warn_unless_match/) {
581 8062 100       16307 $self->check_validation_regexp( $_ => \%args ) if defined $args{$_};
582             }
583 4031 100       7583 $self->setup_grammar_check( \%args ) if defined $args{grammar};
584              
585             # cannot be warped
586 4031 100       7811 $self->set_migrate_from( \%args ) if defined $args{migrate_from};
587              
588             Config::Model::Exception::Model->throw(
589             object => $self,
590             error => "write_as is allowed only with boolean values"
591 4031 50 66     9206 ) if defined $self->{write_as} and $self->{value_type} ne 'boolean';
592              
593 4031 50       9203 Config::Model::Exception::Model->throw(
594             object => $self,
595             error => "Unexpected parameters: " . join( ' ', each %args ) ) if scalar keys %args;
596              
597 4031 100       12218 if ( $self->has_warped_slaves ) {
598 17         159 my $value = $self->_fetch_no_check;
599 17         97 $self->trigger_warp($value);
600             }
601              
602             # when properties are changed, a check is required to validate new constraints
603 4031         37996 $self->needs_check(1);
604              
605 4031         101375 return $self;
606             }
607              
608             # simple but may be overridden
609             sub set_help {
610 4034     4034 0 7580 my ( $self, $args ) = @_;
611 4034 100       10210 return unless defined $args->{help};
612 240         608 $self->{help} = delete $args->{help};
613 240         481 return;
614             }
615              
616             # this code is somewhat dead as warping value_type is no longer supported
617             # but it may come back.
618             sub set_value_type {
619 4034     4034 0 10472 my ( $self, $arg_ref ) = @_;
620              
621 4034   66     18249 my $value_type = delete $arg_ref->{value_type} || $self->value_type;
622              
623 4034 100       8468 Config::Model::Exception::Model->throw(
624             object => $self,
625             error => "Value set: undefined value_type"
626             ) unless defined $value_type;
627              
628 4033         6728 $self->{value_type} = $value_type;
629              
630 4033 100 100     25733 if ( $value_type eq 'boolean' ) {
    100          
    50          
631              
632             # convert any value to boolean
633 628 0       1494 $self->{data} = $self->{data} ? 1 : 0 if defined $self->{data};
    50          
634 628 0       1291 $self->{preset} = $self->{preset} ? 1 : 0 if defined $self->{preset};
    50          
635 628 0       1243 $self->{layered} = $self->{layered} ? 1 : 0 if defined $self->{layered};
    50          
636             }
637             elsif ($value_type eq 'reference'
638             or $value_type eq 'enum' ) {
639 965         1887 my $choice = delete $arg_ref->{choice};
640 965 100       3225 $self->setup_enum_choice($choice) if defined $choice;
641             }
642 4969     4969   9857 elsif (any {$value_type eq $_} qw/string integer number uniline file dir/ ) {
643             Config::Model::Exception::Model->throw(
644             object => $self,
645             error => "'choice' parameter forbidden with type " . $value_type
646 2440 50       5901 ) if defined $arg_ref->{choice};
647             }
648             else {
649 0         0 my $msg =
650             "Unexpected value type : '$value_type' "
651             . "expected 'boolean', 'enum', 'uniline', 'string' or 'integer'."
652             . "Value type can also be set up with a warp relation";
653             Config::Model::Exception::Model->throw( object => $self, error => $msg )
654 0 0       0 unless defined $self->{warp};
655             }
656 4033         10702 return;
657             }
658              
659              
660             sub submit_to_refer_to {
661 55     55 0 112 my $self = shift;
662              
663 55 100       193 if ( defined $self->{refer_to} ) {
    50          
664             $self->{ref_object} = Config::Model::IdElementReference->new(
665             refer_to => $self->{refer_to},
666 51         902 config_elt => $self,
667             );
668             }
669             elsif ( defined $self->{computed_refer_to} ) {
670             $self->{ref_object} = Config::Model::IdElementReference->new(
671             computed_refer_to => $self->{computed_refer_to},
672 4         65 config_elt => $self,
673             );
674              
675             # refer_to registration is done for all element that are used as
676             # variable for complex reference (ie '- $foo' , {foo => '- bar'} )
677 4         29 $self->register_in_other_value( $self->{computed_refer_to}{variables} );
678             }
679             else {
680 0         0 croak "value's submit_to_refer_to: undefined refer_to or computed_refer_to";
681             }
682 55         225 return;
683             }
684              
685 213     213 0 366 sub setup_reference_choice ($self, @args) {
  213         366  
  213         391  
  213         321  
686 213         579 return $self->setup_enum_choice(@args);
687             }
688              
689             sub reference_object {
690 0     0 0 0 my $self = shift;
691 0         0 return $self->{ref_object};
692             }
693              
694             sub built_in {
695 0     0 0 0 carp "warning: built_in sub is deprecated, use upstream_default";
696 0         0 goto &upstream_default;
697             }
698              
699             ## FIXME::what about id ??
700             sub name {
701 10489     10489 1 17216 my $self = shift;
702 10489         28417 my $name = $self->{parent}->name . ' ' . $self->{element_name};
703 10489 100       25262 $name .= ':' . $self->{index_value} if defined $self->{index_value};
704 10489         44586 return $name;
705             }
706              
707             sub get_type {
708 7137     7137 1 15153 return 'leaf';
709             }
710              
711             sub get_cargo_type {
712 6442     6442 0 11538 return 'leaf';
713             }
714              
715             sub can_store {
716 0     0 1 0 my $self = shift;
717              
718 0 0       0 if ( not defined $self->compute ) {
719 0         0 return 1;
720             }
721 0 0       0 if ( $self->compute_obj->allow_user_override ) {
722 0         0 return 1;
723             }
724 0         0 return;
725             }
726              
727             sub get_default_choice {
728 215     215 0 399 my $self = shift;
729 215 100       325 return @{ $self->{backup}{choice} || [] };
  215         1237  
730             }
731              
732             sub get_choice {
733 15     15 1 54 my $self = shift;
734              
735             # just in case the reference_object has been changed
736 15 100 66     93 if ( defined $self->{refer_to} or defined $self->{computed_refer_to} ) {
737 8         25 $self->{ref_object}->get_choice_from_referred_to;
738             }
739              
740 15 50       35 return @{ $self->{choice} || [] };
  15         152  
741             }
742              
743             sub get_info {
744 4     4 1 15 my $self = shift;
745              
746 4         15 my $type = $self->value_type;
747 4 100       19 my @choice = $type eq 'enum' ? $self->get_choice : ();
748 4 100       16 my $choice_str = @choice ? ' (' . join( ',', @choice ) . ')' : '';
749              
750 4         15 my @items = ( 'type: ' . $self->value_type . $choice_str, );
751              
752 4         16 my $std = $self->fetch(qw/mode standard check no/);
753              
754 4 100       52 if ( defined $self->upstream_default ) {
    50          
    100          
    50          
755 1         4 push @items, "upstream_default value: " . $self->map_write_as( $self->upstream_default );
756             }
757             elsif ( defined $std ) {
758 0         0 push @items, "default value: $std";
759             }
760             elsif ( defined $self->refer_to ) {
761 1         15 push @items, "reference to: " . $self->refer_to;
762             }
763             elsif ( defined $self->computed_refer_to ) {
764 0         0 push @items, "computed reference to: " . $self->computed_refer_to;
765             }
766              
767 4         15 my $m = $self->mandatory;
768 4 0       9 push @items, "is mandatory: " . ( $m ? 'yes' : 'no' ) if defined $m;
    50          
769              
770 4         11 foreach my $what (qw/min max warn grammar/) {
771 16         43 my $v = $self->$what();
772 16 50       32 push @items, "$what value: $v" if defined $v;
773             }
774              
775 4         8 foreach my $what (qw/warn_if_match warn_unless_match/) {
776 8         37 my $v = $self->$what();
777 8         36 foreach my $k ( keys %$v ) {
778 0         0 push @items, "$what value: $k";
779             }
780             }
781              
782 4         11 foreach my $what (qw/write_as/) {
783 4         12 my $v = $self->$what();
784 4 100       15 push @items, "$what: @$v" if defined $v;
785             }
786              
787 4         17 return @items ;
788             }
789              
790             sub get_help {
791 52     52 1 5601 my $self = shift;
792              
793 52         100 my $help = $self->{help};
794              
795 52 100       133 return $help unless @_;
796              
797 51         85 my $on_value = shift;
798 51 50       116 return unless defined $on_value;
799              
800 51   66     169 my $fallback = $help->{'.'} || $help -> {'.*'};
801 51         224 foreach my $k (sort { length($b) cmp length($a) } keys %$help) {
  25         64  
802 25 50 33     104 next if $k eq '' or $k eq '.*';
803 25 100       442 return $help->{$k} if $on_value =~ /^$k/;
804             }
805 39         140 return $fallback;
806             }
807              
808             # construct an error message for enum types
809             sub enum_error {
810 9     9 0 29 my ( $self, $value ) = @_;
811 9         16 my @error;
812              
813 9 50       33 if ( not defined $self->{choice} ) {
814 0         0 push @error, "$self->{value_type} type has no defined choice", $self->warp_error;
815 0         0 return @error;
816             }
817              
818 9         76 my @choice = map { "'$_'" } $self->get_choice;
  18         64  
819 9         28 my $var = $self->{value_type};
820 9 50       34 my $str_value = defined $value ? $value : '<undef>';
821 9         52 push @error,
822             "$self->{value_type} type does not know '$value'. Expected " . join( " or ", @choice );
823             push @error,
824 0         0 "Expected list is given by '" . join( "', '", @{ $self->{referred_to_path} } ) . "'"
825 9 50 66     50 if $var eq 'reference' && defined $self->{referred_to_path};
826 9 50       35 push @error, $self->warp_error if $self->{warp};
827              
828 9         31 return @error;
829             }
830              
831 4571     4571   6640 sub _check_value ($self, %args) {
  4571         6736  
  4571         10092  
  4571         6128  
832 4571         8104 my $value = $args{value};
833 4571   50     15994 my $quiet = $args{quiet} || 0;
834 4571   100     13743 my $check = $args{check} || 'yes';
835 4571   100     12402 my $apply_fix = $args{fix} || 0;
836 4571   100     12978 my $mode = $args{mode} || 'backend';
837              
838             #croak "Cannot specify a value with fix = 1" if $apply_fix and exists $args{value} ;
839              
840 4571 100       11359 if ( $logger->is_debug ) {
841 161 100       775 my $v = defined $value ? $value : '<undef>';
842 161         512 my $loc = $self->location;
843 161         651 my $msg =
844             "called from "
845             . join( ' ', caller )
846             . " with value '$v' mode $mode check $check on '$loc'";
847 161         2910 $logger->debug($msg);
848             }
849              
850             # need to keep track to update GUI
851 4571         30028 $self->{nb_of_fixes} = 0; # reset before check
852              
853 4571         8349 my @error;
854             my @warn;
855 4571         10608 my $vt = $self->value_type ;
856              
857 4571 100 100     44336 if ( not defined $value ) {
    50 66        
    100 66        
    100 100        
    100 100        
    100 66        
    100          
    100          
    100          
    100          
    50          
858              
859             # accept with no other check
860             }
861             elsif ( not defined $vt ) {
862 0         0 push @error, "Undefined value_type";
863             }
864             elsif (( $vt =~ /integer/ and $value =~ /^-?\d+$/ )
865             or ( $vt =~ /number/ and $value =~ /^-?\d+(\.\d+)?$/ ) ) {
866              
867             # correct number or integer. check min max
868             push @error, "value $value > max limit $self->{max}"
869 347 100 100     1598 if defined $self->{max} and $value > $self->{max};
870             push @error, "value $value < min limit $self->{min}"
871 347 50 66     1105 if defined $self->{min} and $value < $self->{min};
872             }
873             elsif ( $vt =~ /integer/ and $value =~ /^-?\d+(\.\d+)?$/ ) {
874 1         9 push @error, "Type $vt: value $value is a number " . "but not an integer";
875             }
876             elsif ( $vt eq 'file' or $vt eq 'dir' ) {
877 5 50       30 if (defined $value) {
878 5         17 my $path = path($value);
879 5 100       192 if ($path->exists) {
880 4         93 my $check_sub = 'is_'.$vt ;
881 4 100       12 push @warn, "$value is not a $vt" if not path($value)->$check_sub;
882             }
883             else {
884 1         42 push @warn, "$vt $value does not exists" ;
885             }
886             }
887             }
888             elsif ( $vt eq 'reference' ) {
889              
890             # just in case the reference_object has been changed
891 108 50 66     435 if ( defined $self->{refer_to} or defined $self->{computed_refer_to} ) {
892 108         423 $self->{ref_object}->get_choice_from_referred_to;
893             }
894              
895 108 100 66     832 if ( length($value)
      100        
896             and defined $self->{choice_hash}
897             and not defined $self->{choice_hash}{$value} ) {
898 5 50       38 push @error, ( $quiet ? 'reference error' : $self->enum_error($value) );
899             }
900             }
901             elsif ( $vt eq 'enum' ) {
902 758 100 66     4704 if ( length($value)
      100        
903             and defined $self->{choice_hash}
904             and not defined $self->{choice_hash}{$value} ) {
905 4 50       33 push @error, ( $quiet ? 'enum error' : $self->enum_error($value) );
906             }
907             }
908             elsif ( $vt eq 'boolean' ) {
909             push @error, "error: '$value' is not boolean, i.e. not "
910 246 100       1559 . join ( ' or ', map { "'$_'"} $self->map_write_as(qw/0 1/))
  10         43  
911             unless $value =~ /^[01]$/;
912             }
913             elsif ($vt =~ /integer/
914             or $vt =~ /number/ ) {
915 1         7 push @error, "Value '$value' is not of type " . $vt;
916             }
917             elsif ( $vt eq 'uniline' ) {
918 689 100       1953 push @error, '"uniline" value must not contain embedded newlines (\n)'
919             if $value =~ /\n/;
920             }
921             elsif ( $vt eq 'string' ) {
922              
923             # accepted, no more check
924             }
925             else {
926 0         0 my $choice_msg = '';
927             $choice_msg .= ", choice " . join( " ", $self->get_choice ) . ")"
928 0 0       0 if defined $self->{choice};
929              
930 0         0 my $msg =
931             "Cannot check value_type '$vt' (value '$value'$choice_msg)";
932 0         0 Config::Model::Exception::Model->throw( object => $self, message => $msg );
933             }
934              
935 4571 100 100     14131 if ( defined $self->{match_regexp} and defined $value ) {
936             push @error, "value '$value' does not match regexp " . $self->{match}
937 45 100       361 unless $value =~ $self->{match_regexp};
938             }
939              
940 4571 100       9617 if ( $mode ne 'custom' ) {
941 3864 100       7956 if ( $self->{warn_if_match} ) {
942             my $test_sub = sub {
943 69   50 69   189 my $v = shift // '';
944 69         109 my $r = shift;
945 69 100       755 $v =~ /$r/ ? 0 : 1;
946 93         361 };
947             $self->run_regexp_set_on_value( \$value, $apply_fix, \@warn, 'not ', $test_sub,
948 93         286 $self->{warn_if_match} );
949             }
950              
951 3864 100       8161 if ( $self->{warn_unless_match} ) {
952             my $test_sub = sub {
953 40   50 40   115 my $v = shift // '';
954 40         69 my $r = shift;
955 40 100       495 $v =~ /$r/ ? 1 : 0;
956 28         109 };
957             $self->run_regexp_set_on_value( \$value, $apply_fix, \@warn, '', $test_sub,
958 28         127 $self->{warn_unless_match} );
959             }
960              
961             $self->run_code_set_on_value( \$value, $apply_fix, \@error, $self->{assert} )
962 3864 100       7822 if $self->{assert};
963             $self->run_code_set_on_value( \$value, $apply_fix, \@warn, $self->{warn_unless} )
964 3864 100       7537 if $self->{warn_unless};
965             $self->run_code_set_on_value( \$value, $apply_fix, \@warn, $self->{warn_if}, 1 )
966 3864 100       7867 if $self->{warn_if};
967             }
968              
969             # unconditional warn
970 4571 100 100     13436 push @warn, $self->{warn} if defined $value and $self->{warn};
971              
972 4571 100 100     10910 if ( defined $self->{validation_parser} and defined $value ) {
973 5         10 my $prd = $self->{validation_parser};
974 5         11 my ( $err_msg, $warn_msg ) = ( '', '' );
975 5         46 my $prd_check = $prd->check( $value, 1, $self, \$err_msg, \$warn_msg );
976 5 100       4832 my $prd_result = defined $prd_check ? 1 : 0;
977 5 100       33 $logger->debug( "grammar check on $value returned ", defined $prd_check ? $prd_check : '<undef>' );
978 5 100       46 if (not $prd_result) {
979 2         5 my $msg = "value '$value' does not match grammar from model";
980 2 50       6 $msg .= ": $err_msg" if $err_msg;
981 2         5 push @error, $msg;
982             }
983 5 50       11 push @warn, $warn_msg if $warn_msg;
984             }
985              
986             $logger->debug(
987 4571         14754 "check_value returns ",
988             scalar @error,
989             " errors and ", scalar @warn, " warnings"
990             );
991              
992             # return $value because it may be modified by apply_fixes
993 4571         49211 return ($value, \@error, \@warn);
994             }
995              
996 4464     4464   6565 sub _check_mandatory_value ($self, %args) {
  4464         6293  
  4464         13026  
  4464         6085  
997 4464         7256 my $value = $args{value};
998 4464   100     12422 my $check = $args{check} || 'yes';
999 4464   100     11427 my $mode = $args{mode} || 'backend';
1000 4464   33     9874 my $error = $args{error} // carp "Missing error parameter";
1001              
1002             # a value may be mandatory and have a default value with layers
1003 4464 100 100     14653 if ( $self->{mandatory}
      66        
      66        
      100        
      66        
      100        
1004             and $check eq 'yes'
1005             and ( $mode =~ /backend|user/ )
1006             and ( not defined $value or not length($value) )
1007             and ( not defined $self->{layered} or not length($self->{layered}))
1008             ) {
1009             # check only "empty" mode.
1010 14         52 my $msg = "Undefined mandatory value.";
1011             $msg .= $self->warp_error
1012 14 50       64 if defined $self->{warped_attribute}{default};
1013 14         44 push $error->@*, $msg;
1014             }
1015              
1016 4464         9801 return;
1017             }
1018              
1019 4464     4464 1 7522 sub check_value ($self, @args) {
  4464         6310  
  4464         10889  
  4464         5852  
1020 4464         11155 my ($value, $error, $warn) = $self->_check_value(@args);
1021 4464         15113 $self->_check_mandatory_value(@args, value => $value, error => $error);
1022 4464         14652 $self->clear_errors;
1023 4464         49999 $self->clear_warnings;
1024 4464 100       39525 $self->add_error(@$error) if @$error;
1025 4464 100       9535 $self->add_warning(@$warn) if @$warn;
1026              
1027 4464         12989 $logger->trace("done");
1028              
1029 4464         33006 my $ok = not $error->@*;
1030             # return $value because it may be updated by apply_fix
1031 4464 100       16382 return wantarray ? ($ok, $value) : $ok;
1032             }
1033              
1034             sub run_code_on_value {
1035 184     184 0 439 my ( $self, $value_r, $apply_fix, $array, $label, $sub, $msg, $fix ) = @_;
1036              
1037 184         937 $logger->info( $self->location . ": run_code_on_value called (apply_fix $apply_fix)" );
1038              
1039 184         3160 my $ret = $sub->($$value_r);
1040 184 100       610 if ( $logger->is_debug ) {
1041 83 50       388 my $str = defined $ret ? $ret : '<undef>';
1042 83         280 $logger->debug("run_code_on_value sub returned '$str'");
1043             }
1044              
1045 184 100       1885 unless ($ret) {
1046 97         284 $logger->debug("run_code_on_value sub returned false");
1047 97 100       1076 $msg =~ s/\$_/$$value_r/g if defined $$value_r;
1048 97 100       262 if ($msg =~ /\$std_value/) {
1049 6         20 my $std = $self->_fetch_std_no_check ;
1050 6 100       26 $msg =~ s/\$std_value/$std/g if defined $std;
1051             }
1052 97 50       223 $msg .= " (this cannot be fixed with 'cme fix' command)" unless $fix;
1053 97 100       235 push @$array, $msg unless $apply_fix;
1054 97 100 66     483 $self->{nb_of_fixes}++ if ( defined $fix and not $apply_fix );
1055 97 100 66     375 $self->apply_fix( $fix, $value_r, $msg ) if ( defined $fix and $apply_fix );
1056             }
1057 184         895 return;
1058             }
1059              
1060             # function that may be used in eval'ed code to use file in there (in
1061             # run_code_set_on_value and apply_fix). Using this function is
1062             # mandatory for tests that are done in pseudo root
1063             # directory. Necessary for relative path (although chdir in and out of
1064             # root_dir could work) and for absolute path (where chdir in and out
1065             # of root_dir would not work without using chroot)
1066              
1067             {
1068             # val is a value object. Use this trick so eval'ed code can
1069             # use file() function instead of $file->() sub ref
1070             my $val ;
1071             sub set_val {
1072 112     112 0 191 return $val = shift;
1073             }
1074             sub file {
1075 4     4 1 21 return $val->root_path->child(shift);
1076             }
1077             }
1078              
1079             sub run_code_set_on_value {
1080 75     75 0 177 my ( $self, $value_r, $apply_fix, $array, $w_info, $invert ) = @_;
1081              
1082 75         189 $self->set_val;
1083              
1084 75         260 foreach my $label ( sort keys %$w_info ) {
1085 75         162 my $code = $w_info->{$label}{code};
1086 75   33     191 my $msg = $w_info->{$label}{msg} || $label;
1087 75         286 $logger->trace("eval'ed code is: '$code'");
1088 75         867 my $fix = $w_info->{$label}{fix};
1089              
1090             my $sub = sub {
1091 75     75   140 local $_ = shift;
1092             ## no critic (TestingAndDebugging::ProhibitNoWarning)
1093 59     59   682 no warnings "uninitialized";
  59         149  
  59         48813  
1094 75         6331 my $ret = eval($code); ## no critic (ProhibitStringyEval)
1095 75 50       912 if ($@) {
1096 0         0 Config::Model::Exception::Model->throw(
1097             object => $self,
1098             message => "Eval of assert or warning code failed : $@"
1099             );
1100             }
1101 75   100     383 return ($invert xor $ret) ;
1102 75         340 };
1103              
1104 75         220 $self->run_code_on_value( $value_r, $apply_fix, $array, $label, $sub, $msg, $fix );
1105             }
1106 75         178 return;
1107             }
1108              
1109             sub run_regexp_set_on_value {
1110 121     121 0 294 my ( $self, $value_r, $apply_fix, $array, $may_be, $test_sub, $w_info ) = @_;
1111              
1112             # no need to check default or computed values
1113 121 100       306 return unless defined $$value_r;
1114              
1115 97         330 foreach my $rxp ( sort keys %$w_info ) {
1116             # $_[0] is set to $$value_r when $sub is called
1117 109     109   306 my $sub = sub { $test_sub->( $_[0], $rxp ) };
  109         250  
1118 109   66     410 my $msg = $w_info->{$rxp}{msg} || "value should ${may_be}match regexp '$rxp'";
1119 109         221 my $fix = $w_info->{$rxp}{fix};
1120 109         263 $self->run_code_on_value( $value_r, $apply_fix, $array, 'regexp', $sub, $msg, $fix );
1121             }
1122             return
1123 97         333 }
1124              
1125             sub has_fixes {
1126 9     9 1 3486 my $self = shift;
1127 9         46 return $self->{nb_of_fixes};
1128             }
1129              
1130             sub apply_fixes {
1131 94     94 1 2412 my $self = shift;
1132              
1133 94 100       271 if ( $logger->is_trace ) {
1134 4         40 $fix_logger->trace( "called for " . $self->location );
1135             }
1136              
1137 94         769 my ( $old, $new );
1138 94         162 my $i = 0;
1139             do {
1140 94   100     312 $old = $self->{nb_of_fixes} // 0;
1141 94         271 $self->check_value( value => $self->_fetch_no_check, fix => 1 );
1142              
1143 94         183 $new = $self->{nb_of_fixes};
1144 94         232 $self->check_value( value => $self->_fetch_no_check );
1145             # if fix fails, try and check_fix call each other until this limit is found
1146 94 50       409 if ( $i++ > 20 ) {
1147 0         0 Config::Model::Exception::Model->throw(
1148             object => $self,
1149             error => "Too many fix loops: check code used to fix value or the check"
1150             );
1151             }
1152 94   66     139 } while ( $self->{nb_of_fixes} and $old > $new );
1153              
1154 94         210 $self->show_warnings($self->_fetch_no_check);
1155 94         455 return;
1156             }
1157              
1158             # internal: called by check when a fix is required
1159             sub apply_fix {
1160 37     37 0 97 my ( $self, $fix, $value_r, $msg ) = @_;
1161              
1162 37         81 local $_ = $$value_r; # used inside $fix sub ref
1163              
1164 37 100       98 if ( $fix_logger->is_info ) {
1165 4         23 my $str = $fix;
1166 4         17 $str =~ s/\n/ /g;
1167 4         24 $fix_logger->info( $self->location . ": Applying fix '$str'" );
1168             }
1169              
1170 37         300 $self->set_val;
1171              
1172 37         3410 eval($fix); ## no critic (ProhibitStringyEval)
1173 37 50       241 if ($@) {
1174 0         0 Config::Model::Exception::Model->throw(
1175             object => $self,
1176             message => "Eval of fix $fix failed : $@"
1177             );
1178             }
1179              
1180             ## no critic (TestingAndDebugging::ProhibitNoWarning)
1181 59     59   530 no warnings "uninitialized";
  59         147  
  59         18888  
1182 37 100       116 if ( $_ ne $$value_r ) {
1183 34         266 $fix_logger->info( $self->location . ": fix changed value from '$$value_r' to '$_'" );
1184 34         375 $self->_store_fix( $$value_r, $_, $msg );
1185 34         69 $$value_r = $_; # so chain of fixes work
1186             }
1187             else {
1188 3         19 $fix_logger->info( $self->location . ": fix did not change value '$$value_r'" );
1189             }
1190 37         104 return;
1191             }
1192              
1193             sub _store_fix {
1194 34     34   95 my ( $self, $old, $new, $msg ) = @_;
1195              
1196 34         87 $self->{data} = $new;
1197              
1198 34 100       96 if ( $fix_logger->is_trace ) {
1199 4   100     60 $fix_logger->trace(
      100        
1200             "fix change: '" . ( $old // '<undef>' ) . "' -> '" . ( $new // '<undef>' ) . "'"
1201             );
1202             }
1203              
1204 34   100     277 my $new_v = $new // $self->_fetch_std ;
1205 34   66     86 my $old_v = $old // $self->_fetch_std;
1206              
1207 34 100       83 if ( $fix_logger->is_trace ) {
1208 4   100     40 $fix_logger->trace(
      100        
1209             "fix change (with std value)): '" . ( $old // '<undef>' ) . "' -> '" . ( $new // '<undef>' ) . "'"
1210             );
1211             }
1212              
1213             ## no critic (TestingAndDebugging::ProhibitNoWarning)
1214 59     59   543 no warnings "uninitialized";
  59         158  
  59         13274  
1215             # in case $old is the default value and $new is undef
1216 34 100       224 if ($old_v ne $new_v) {
1217 33 50       189 $self->notify_change(
1218             old => $old_v,
1219             new => $new_v,
1220             note => 'applied fix'. ( $msg ? ' for :'. $msg : '')
1221             );
1222 33 100 100     159 $self->trigger_warp($new_v) if defined $new_v and $self->has_warped_slaves;
1223             }
1224 34         289 return;
1225             }
1226              
1227             # read checks should be blocking
1228              
1229             sub check {
1230 6577     6577 1 20240 goto &check_fetched_value;
1231             }
1232              
1233 6577     6577 0 10019 sub check_fetched_value ($self, @args) {
  6577         9099  
  6577         14859  
  6577         9286  
1234 6577 100       14540 if ( $logger->is_debug ) {
1235             ## no critic (TestingAndDebugging::ProhibitNoWarning)
1236 59     59   516 no warnings 'uninitialized';
  59         158  
  59         44454  
1237 62         484 $logger->debug( "called for " . $self->location . " from " . join( ' ', caller ),
1238             " with @args" );
1239             }
1240              
1241             my %args =
1242             @args == 0 ? ( value => $self->{data} )
1243 6577 50       55112 : @args == 1 ? ( value => $args[0] )
    100          
1244             : @args;
1245              
1246 6577 50       16880 my $value = exists $args{value} ? $args{value} : $self->{data};
1247 6577   50     19715 my $silent = $args{silent} || 0;
1248 6577   50     17120 my $check = $args{check} || 'yes';
1249              
1250 6577 100       17967 if ( $self->needs_check ) {
1251 1719         50793 $self->check_value(%args);
1252              
1253 1719         4651 my $err_count = $self->has_error;
1254 1719         12746 my $warn_count = $self->has_warning;
1255 1719         14295 $logger->debug("done with $err_count errors and $warn_count warnings");
1256              
1257 1719 100 100     17079 $self->needs_check(0) unless $err_count or $warn_count;
1258             }
1259             else {
1260 4858         141380 $logger->debug("is not needed");
1261             }
1262              
1263 6577         92320 $self->show_warnings($value, $silent);
1264              
1265 6577 50       18496 return wantarray ? $self->all_errors : $self->is_ok;
1266             }
1267              
1268 8572     8572 0 13905 sub show_warnings ($self, $value, $silent = 0) {
  8572         12414  
  8572         12697  
  8572         12886  
  8572         11877  
1269             # old_warn is used to avoid warning the user several times for the
1270             # same reason (i.e. when storing and fetching value). We take care
1271             # to clean up this hash each time store is run
1272 8572   100     25518 my $old_warn = $self->{old_warning_hash} || {};
1273 8572         12696 my %warn_h;
1274              
1275 8572 100 100     21276 if ( $self->has_warning and not $nowarning and not $silent ) {
      66        
1276 47   100     522 my $str = $value // '<undef>';
1277 47         97 chomp $str;
1278 47 100       194 my $w_str = $str =~ /\n/ ? "\n+++++\n$str\n+++++" : "'$str'";
1279 47         1937 foreach my $w ( $self->all_warnings ) {
1280 53         738 $warn_h{$w} = 1;
1281 53         321 my $w_msg = "Warning in '" . $self->location_short . "': $w\nOffending value: $w_str";
1282 53 100       136 if ($old_warn->{$w}) {
1283             # user has already seen the warning, let's use debug level (required by tests)
1284 7         17 $user_logger->debug($w_msg);
1285             }
1286             else {
1287 46         147 $user_logger->warn($w_msg);
1288             }
1289             }
1290             }
1291 8572         73225 $self->{old_warning_hash} = \%warn_h;
1292 8572         18272 return;
1293             }
1294              
1295 1977     1977 1 40076 sub store ($self, @args) {
  1977         3172  
  1977         4112  
  1977         2754  
1296 1977 50       7684 my %args =
    100          
1297             @args == 1 ? ( value => $args[0] )
1298             : @args == 3 ? ( 'value', @args )
1299             : @args;
1300 1977         6674 my $check = $self->_check_check( $args{check} );
1301 1977   100     7151 my $silent = $args{silent} || 0;
1302              
1303 1977   100     4989 my $str = $args{value} // '<undef>';
1304 1977 100       5055 $logger->debug( "called with '$str' on ", $self->composite_name ) if $logger->is_debug;
1305              
1306             # store with check skip makes sense when force loading data: bad value
1307             # is discarded, partially consistent values are stored so the user may
1308             # salvage them before next save check discard them
1309              
1310             # $self->{data} represents what written in the file
1311 1977         12875 my $old_value = $self->{data};
1312              
1313 1977         3607 my $incoming_value = $args{value};
1314 1977 100       7203 $self->transform_boolean( \$incoming_value ) if $self->value_type eq 'boolean';
1315              
1316 1977         5158 my $value = $self->transform_value( value => $incoming_value, check => $check );
1317              
1318             ## no critic (TestingAndDebugging::ProhibitNoWarning)
1319 59     59   577 no warnings qw/uninitialized/;
  59         159  
  59         13953  
1320 1976 100       8108 if ($self->instance->initial_load) {
1321             # may send more than one notification
1322 804 100       1652 if ( $incoming_value ne $value ) {
1323             # data was transformed by model
1324 21         115 $self->notify_change(really => 1, old => $incoming_value , new => $value, note =>"initial value changed by model");
1325             }
1326 804 100 100     2033 if (defined $old_value and $old_value ne $value) {
1327 1         7 $self->notify_change(really => 1, old => $old_value , new => $value, note =>"conflicting initial values");
1328             }
1329 804 100 100     1744 if (defined $old_value and $old_value eq $value) {
1330 2         12 $self->notify_change(really => 1, note =>"removed redundant initial value");
1331             }
1332             }
1333              
1334 1976 100 100     5084 if ( defined $old_value and $value eq $old_value ) {
1335 75 100       278 $logger->info( "skip storage of ", $self->composite_name, " unchanged value: $value" )
1336             if $logger->is_info;
1337 75         732 return 1;
1338             }
1339              
1340 59     59   515 use warnings qw/uninitialized/;
  59         151  
  59         15534  
1341              
1342 1901         6393 $self->needs_check(1); # always when storing a value
1343              
1344 1901         45305 my ($ok, $fixed_value) = $self->check_stored_value(
1345             value => $value,
1346             check => $check,
1347             silent => $silent,
1348             );
1349              
1350 1901         7774 $self->_store( %args, ok => $ok, value => $value, check => $check );
1351              
1352 1897         3877 my $user_cb = $args{callback} ;
1353 1897 100       3999 $user_cb->(%args) if $user_cb;
1354              
1355 1897   100     12742 return $ok || ($check eq 'no');
1356             }
1357              
1358             #
1359             # New subroutine "_store_value" extracted - Wed Jan 16 18:46:22 2013.
1360             #
1361             sub _store_value {
1362 1885     1885   2905 my $self = shift;
1363 1885         3220 my $value = shift;
1364 1885   50     6245 my $notify_change = shift // 1;
1365              
1366 1885 100       8696 if ( $self->instance->layered ) {
    100          
1367 133         497 $self->{layered} = $value;
1368             }
1369             elsif ( $self->instance->preset ) {
1370 11 50       114 $self->notify_change( check_done => 1, old => $self->{data}, new => $value )
1371             if $notify_change;
1372 11         57 $self->{preset} = $value;
1373             }
1374             else {
1375             ## no critic (TestingAndDebugging::ProhibitNoWarning)
1376 59     59   540 no warnings 'uninitialized';
  59         165  
  59         179587  
1377 1741   100     5968 my $old = $self->{data} // $self->_fetch_std;
1378 1741   100     5934 my $new = $value // $self->_fetch_std;
1379 1741 100 66     10834 $self->notify_change(
1380             check_done => 1,
1381             old => $old,
1382             new => $new
1383             ) if $notify_change and ( $old ne $new );
1384 1741         4714 $self->{data} = $value; # may be undef
1385             }
1386 1885         3306 return $value;
1387             }
1388              
1389             # this method is overriden in layered Value
1390 1901     1901   2760 sub _store ($self, %args) {
  1901         2861  
  1901         6733  
  1901         2685  
1391             my ( $value, $check, $silent, $notify_change, $ok ) =
1392 1901         5788 @args{qw/value check silent notify_change ok/};
1393              
1394 1901 100       5107 if ( $logger->is_debug ) {
1395 105         548 my $i = $self->instance;
1396 105   100     439 my $msg = "value store ". ($value // '<undef>')." ok '$ok', check is $check";
1397 105 100       237 for ( qw/layered preset/ ) { $msg .= " $_" if $i->$_() }
  210         734  
1398 105         283 $logger->debug($msg);
1399             }
1400              
1401 1901         14089 my $old_value = $self->_fetch_no_check;
1402              
1403             # let's store wrong value when check is disable (gh #15)
1404 1901 100 100     5096 if ( $ok or $check eq 'no' ) {
1405 1880         10692 $self->instance->cancel_error( $self->location );
1406 1880         25894 $self->_store_value( $value, $notify_change );
1407             }
1408             else {
1409 21         155 $self->instance->add_error( $self->location );
1410 21 100       950 if ($check eq 'skip') {
1411 18 100 66     88 if (not $silent and $self->has_error) {
1412 6         112 my $msg = "Warning: ".$self->location." skipping value $value because of the following errors:\n"
1413             . $self->error_msg . "\n\n";
1414             # fuse UI exits when a warning is issued. No other need to advertise this option
1415 6 50       27 print $msg if $args{say_dont_warn};
1416 6 50       40 $user_logger->warn($msg) unless $args{say_dont_warn};
1417             }
1418             }
1419             else {
1420 3         20 Config::Model::Exception::WrongValue->throw(
1421             object => $self,
1422             error => $self->error_msg
1423             );
1424             }
1425             }
1426              
1427 1898 50 100     9879 if ( $ok
      100        
      66        
      66        
      33        
      33        
1428             and defined $value
1429             and $self->has_warped_slaves
1430             and ( not defined $old_value or $value ne $old_value )
1431             and not( $self->instance->layered or $self->instance->preset ) ) {
1432 100         2066 $self->trigger_warp($value);
1433             }
1434              
1435 1897 100       17241 $logger->trace( "_store done on ", $self->composite_name ) if $logger->is_trace;
1436 1897         13853 return;
1437             }
1438              
1439             #
1440             # New subroutine "transform_boolean" extracted - Thu Sep 19 18:58:21 2013.
1441             #
1442             sub transform_boolean {
1443 242     242 0 423 my $self = shift;
1444 242         407 my $v_ref = shift;
1445              
1446 242 100       652 return unless defined $$v_ref;
1447              
1448 239 100       681 if ( my $wa = $self->{write_as} ) {
1449 37         78 my $i = 0;
1450 37         148 for ( @$wa ) {
1451 74 100       217 $$v_ref = $i if ( $wa->[$i] eq $$v_ref );
1452 74         171 $i++
1453             }
1454             }
1455              
1456             # convert yes no to 1 or 0
1457 239 100       1365 $$v_ref = 1 if ( $$v_ref =~ /^(y|yes|true|on)$/i );
1458 239 100 100     1318 $$v_ref = 0 if ( $$v_ref =~ /^(n|no|false|off)$/i or length($$v_ref) == 0);
1459 239         466 return;
1460             }
1461              
1462             # internal. return ( undef, value)
1463             # May return an undef value if actual store should be skipped
1464 1977     1977 0 2890 sub transform_value ($self, @args) {
  1977         2891  
  1977         4305  
  1977         2710  
1465 1977 50       6542 my %args = @args > 1 ? @args : ( value => $args[0] );
1466 1977         3796 my $value = $args{value};
1467 1977   50     4794 my $check = $args{check} || 'yes';
1468              
1469 1977         4693 my $inst = $self->instance;
1470              
1471             $self->warp
1472             if ($self->{warp}
1473             and defined $self->{warp_info}
1474 1977 50 66     6009 and @{ $self->{warp_info}{computed_master} } );
  0   33     0  
1475              
1476 1977 100 100     10124 if ( defined $self->compute_obj
1477             and not $self->compute_obj->allow_user_override ) {
1478 1         3 my $msg = 'assignment to a computed value is forbidden unless '
1479             . 'compute -> allow_override is set.';
1480 1 50       24 Config::Model::Exception::Model->throw( object => $self, message => $msg )
1481             if $check eq 'yes';
1482 0         0 return;
1483             }
1484              
1485 1976 100 100     8255 if ( defined $self->{refer_to} or defined $self->{computed_refer_to} ) {
1486 44         210 $self->{ref_object}->get_choice_from_referred_to;
1487             }
1488              
1489             $value = $self->{convert_sub}($value)
1490 1976 100 66     6757 if ( defined $self->{convert_sub} and defined $value );
1491              
1492             # apply replace on store *before* check is done, so a bad value
1493             # can be replaced with a good one
1494 1976 100 66     4745 $value = $self->apply_replace($value) if ($self->{replace} and defined $value);
1495              
1496             # using default or computed value is normally done on fetch. Except that an undefined
1497             # value cannot be stored in a mandatory value. Storing undef is used when resetting a
1498             # value to default. If a value is mandatory, we must store the default (or best equivalent)
1499             # instead
1500 1976 100 100     8379 if ( ( not defined $value or not length($value) ) and $self->mandatory ) {
      100        
1501 2         8 delete $self->{data}; # avoiding recycling the old stored value
1502 2         8 $value = $self->_fetch_no_check;
1503             }
1504              
1505 1976         6741 return $value;
1506             }
1507              
1508             sub apply_replace {
1509 6     6 0 16 my ($self, $value) = @_;
1510              
1511 6 100       25 if ( defined $self->{replace}{$value} ) {
1512 4         24 $logger->debug("store replacing value $value with $self->{replace}{$value}");
1513 4         39 $value = $self->{replace}{$value};
1514             }
1515             else {
1516 2         14 foreach my $k ( keys %{ $self->{replace} } ) {
  2         13  
1517 4 100       80 if ( $value =~ /^$k$/ ) {
1518 1         16 $logger->debug(
1519             "store replacing value $value (matched /$k/) with $self->{replace}{$k}");
1520 1         12 $value = $self->{replace}{$k};
1521 1         9 last;
1522             }
1523             }
1524             }
1525 6         17 return $value;
1526             }
1527              
1528 1901     1901 0 2999 sub check_stored_value ($self, %args) {
  1901         3136  
  1901         5284  
  1901         2758  
1529 1901         6386 my ($ok, $fixed_value) = $self->check_value( %args );
1530              
1531             my ( $value, $check, $silent ) =
1532 1901         5840 @args{qw/value check silent/};
1533              
1534 1901 100 100     5164 $self->needs_check(0) unless $self->has_error or $self->has_warning;
1535              
1536             # must always warn when storing a value, hence clearing the list
1537             # of already issued warnings
1538 1901         43233 $self->{old_warning_hash} = {};
1539 1901         6423 $self->show_warnings($value, $silent);
1540              
1541 1901 50       8770 return wantarray ? ($ok,$fixed_value) : $ok;
1542             }
1543              
1544             # print a hopefully helpful error message when value_type is not
1545             # defined
1546             sub _value_type_error {
1547 0     0   0 my $self = shift;
1548              
1549             Config::Model::Exception::Model->throw(
1550             object => $self,
1551             message => 'value_type is undefined'
1552 0 0       0 ) unless defined $self->{warp};
1553              
1554 0         0 my $str = "Item " . $self->{element_name} . " is not available. " . $self->warp_error;
1555              
1556 0         0 Config::Model::Exception::User->throw( object => $self, message => $str );
1557 0         0 return;
1558             }
1559              
1560 435     435 1 745 sub load_data ($self, @args) {
  435         637  
  435         1046  
  435         595  
1561 435 100       1465 my %args = @args > 1 ? @args : ( data => $args[0] );
1562 435   33     1321 my $data = delete $args{data} // delete $args{value};
1563              
1564 435         786 my $rd = ref $data;
1565              
1566 435 50 33 0   1062 if ( $rd and any { $rd eq $_ } qw/ARRAY HASH SCALAR/) {
  0         0  
1567 0         0 Config::Model::Exception::LoadData->throw(
1568             object => $self,
1569             message => "load_data called with non scalar arg",
1570             wrong_data => $data,
1571             );
1572             }
1573             else {
1574 435 100       1251 if ( $logger->is_info ) {
1575 41   50     196 my $str = $data // '<undef>';
1576 41         233 $logger->info( "Value load_data (", $self->location, ") will store value $str" );
1577             }
1578 435         3730 return $self->store(%args, value => $data);
1579             }
1580 0         0 return;
1581             }
1582              
1583             sub fetch_custom {
1584 80     80 1 886 my $self = shift;
1585 80         191 return $self->fetch(mode => 'custom');
1586             }
1587              
1588             sub fetch_standard {
1589 9     9 1 813 my $self = shift;
1590 9         34 return $self->fetch(mode => 'standard');
1591             }
1592              
1593             sub has_data {
1594 10     10 1 1595 my $self = shift;
1595 10 100       33 return (defined $self->fetch(qw/mode custom check no silent 1/)) ? 1 : 0 ;
1596             }
1597              
1598             sub _init {
1599 3484     3484   5773 my $self = shift;
1600              
1601             # trigger loop
1602             #$self->{warper} -> trigger if defined $self->{warper} ;
1603             # if ($self->{warp} and defined $self->{warp_info}
1604             # and @{$self->{warp_info}{computed_master}});
1605              
1606 3484 100 100     14417 if ( defined $self->{refer_to} or defined $self->{computed_refer_to} ) {
1607 55         295 $self->submit_to_refer_to;
1608 55         261 $self->{ref_object}->get_choice_from_referred_to;
1609             }
1610 3482         6200 return;
1611             }
1612              
1613             # returns something that needs to be written to config file
1614             # unless overridden by user data
1615             sub _fetch_std {
1616 9552     9552   17203 my ( $self, $check ) = @_;
1617              
1618 9552 50 33     23739 if ( not defined $self->{value_type} and $check eq 'yes' ) {
1619 0         0 $self->_value_type_error;
1620             }
1621              
1622             # get stored value or computed value or default value
1623 9552         13085 my $std_value;
1624              
1625 9552         14800 eval {
1626             $std_value =
1627             defined $self->{preset} ? $self->{preset}
1628             : $self->compute_is_default ? $self->perform_compute
1629 9552 100       43673 : $self->{default};
    100          
1630             };
1631              
1632 9552         16615 my $e = $@;;
1633 9552 100 66     30188 if ( ref($e) and $e->isa('Config::Model::Exception::User') ) {
    50          
    50          
1634 4 100       16 if ( $check eq 'yes' ) {
1635 2         12 $e->rethrow;
1636             }
1637 2         6 $std_value = undef;
1638             }
1639             elsif ( ref($e) ) {
1640 0         0 $e->rethrow ;
1641             }
1642             elsif ($e) {
1643 0         0 die $e;
1644             }
1645              
1646 9550         19420 return $std_value;
1647             }
1648              
1649             # use when std_value is needed to create error or warning message
1650             # within a check sub. Using _fetch_std leads to deep recursions
1651             sub _fetch_std_no_check {
1652 6     6   13 my ( $self, $check ) = @_;
1653              
1654             # get stored value or computed value or default value
1655 6         8 my $std_value;
1656              
1657 6         11 eval {
1658             $std_value =
1659             defined $self->{preset} ? $self->{preset}
1660             : $self->compute_is_default ? $self->compute_obj->compute
1661 6 50       23 : $self->{default};
    50          
1662             };
1663              
1664 6 50       16 if ($@) {
1665 0         0 $logger->debug("eval got error: $@");
1666             }
1667              
1668 6         13 return $std_value;
1669             }
1670              
1671             my %old_mode = (
1672             built_in => 'upstream_default',
1673             non_built_in => 'non_upstream_default',
1674             );
1675              
1676             {
1677             my %accept_mode = map { ( $_ => 1 ) } qw/custom standard preset default upstream_default
1678             layered non_upstream_default allow_undef user backend/;
1679              
1680             sub is_bad_mode {
1681 16176     16176 1 30357 my ($self, $mode) = @_;
1682 16176 50 33     78417 if ( $mode and not defined $accept_mode{$mode} ) {
1683 0         0 my $good_ones = join( ' or ', sort keys %accept_mode );
1684 0         0 return "expected $good_ones as mode parameter, not $mode";
1685             }
1686             }
1687             }
1688              
1689             sub _fetch {
1690 8013     8013   15384 my ( $self, $mode, $check ) = @_;
1691 8013 100       16758 $logger->trace( "called for " . $self->location ) if $logger->is_trace;
1692              
1693             # always call to perform submit_to_warp
1694 8013         45511 my $pref = $self->_fetch_std( $check );
1695              
1696 8011         17564 my $data = $self->{data};
1697 8011 100 100     20271 if ( defined $pref and not $self->{notified_change_for_default} and not defined $data ) {
      100        
1698 170         506 $self->{notified_change_for_default} = 1;
1699 170 100       848 my $info = defined $self->{preset} ? 'preset'
    100          
1700             : $self->compute_is_default ? 'computed'
1701             : 'default';
1702 170         872 $self->notify_change( old => undef, new => $pref, note => "use $info value" );
1703             }
1704              
1705 8011         14628 my $layer_data = $self->{layered};
1706             my $known_upstream =
1707             defined $layer_data ? $layer_data
1708             : $self->compute_is_upstream_default ? $self->perform_compute
1709 8011 100       30179 : $self->{upstream_default};
    100          
1710 8011 100       16433 my $std = defined $pref ? $pref : $known_upstream;
1711              
1712 8011 100 100     18962 if ( defined $self->{_migrate_from} and not defined $data ) {
1713 23         73 $data = $self->migrate_value;
1714             }
1715              
1716 8011         21408 foreach my $k ( keys %old_mode ) {
1717 16022 50       34157 next unless $mode eq $k;
1718 0         0 $mode = $old_mode{$k};
1719 0         0 carp $self->location, " warning: deprecated mode parameter: $k, ", "expected $mode\n";
1720             }
1721              
1722 8011 50       18519 if (my $err = $self->is_bad_mode($mode)) {
1723 0         0 croak "fetch_no_check: $err";
1724             }
1725              
1726 8011 100       18768 if ( $mode eq 'custom' ) {
1727             ## no critic (TestingAndDebugging::ProhibitNoWarning)
1728 59     59   598 no warnings "uninitialized";
  59         165  
  59         6772  
1729 3082         4450 my $cust;
1730             $cust = $data
1731             if $data ne $pref
1732             and $data ne $self->{upstream_default}
1733 3082 100 100     11170 and $data ne $layer_data;
      100        
1734 3082 50       7750 $logger->debug( "custom mode result '$cust' for " . $self->location )
1735             if $logger->is_debug;
1736 3082         19477 return $cust;
1737             }
1738              
1739 4929 100       9647 if ( $mode eq 'non_upstream_default' ) {
1740             ## no critic (TestingAndDebugging::ProhibitNoWarning)
1741 59     59   510 no warnings "uninitialized";
  59         152  
  59         137403  
1742 6         23 my $nbu;
1743 6         15 foreach my $d ($data, $layer_data, $pref) {
1744 9 100 66     38 if ( defined $d and $d ne $self->{upstream_default} ) {
1745 5         10 $nbu = $d;
1746 5         14 last;
1747             }
1748             }
1749              
1750 6 50       26 $logger->debug( "done in non_upstream_default mode for " . $self->location )
1751             if $logger->is_debug;
1752 6         46 return $nbu;
1753             }
1754              
1755 4923         6796 my $res;
1756 4923 100   19432   24841 if (any {$_ eq $mode} qw/preset default upstream_default layered/) {
  19432 100       37453  
    100          
    50          
1757 95         188 $res = $self->{$mode};
1758             }
1759             elsif ( $mode eq 'standard') {
1760 50         117 $res = $std;
1761             }
1762             elsif ( $mode eq 'backend') {
1763 2782         6258 $res = $self->_data_or_alt($data, $pref);
1764             }
1765 2469     2469   5232 elsif (any {$mode eq $_} qw/user allow_undef/) {
1766 1996         4314 $res = $self->_data_or_alt($data, $std);
1767             }
1768             else {
1769 0         0 die "unexpected mode $mode ";
1770             }
1771              
1772 4923 100 100     18314 $logger->debug( "done in '$mode' mode for " . $self->location . " -> " . ( $res // '<undef>' ) )
1773             if $logger->is_debug;
1774              
1775 4923         33682 return $res;
1776             }
1777              
1778 4778     4778   7027 sub _data_or_alt ($self, $data, $alt) {
  4778         6707  
  4778         7010  
  4778         7122  
  4778         5921  
1779 4778         6288 my $res;
1780 4778         11470 my $vt = $self->value_type;
1781              
1782 4778 100   13086   15391 if (any {$_ eq $vt} qw/integer boolean number/) {
  13086         20553  
1783 1021   100     3232 $res = $data // $alt
1784             }
1785             else {
1786             # empty string is considered as undef, but empty string is
1787             # still returned if there's not defined alternative ($alt)
1788 3757 100 66     11396 $res = length($data) ? $data : $alt // $data
1789             }
1790 4778         16741 return $res;
1791             }
1792              
1793             sub fetch_no_check {
1794 0     0 0 0 my $self = shift;
1795 0         0 carp "fetch_no_check is deprecated. Use fetch (check => 'no')";
1796 0         0 return $self->fetch( check => 'no' );
1797             }
1798              
1799             # likewise but without any warp, etc related check
1800             sub _fetch_no_check {
1801 2214     2214   3903 my $self = shift;
1802             return
1803             defined $self->{data} ? $self->{data}
1804             : defined $self->{preset} ? $self->{preset}
1805             : defined $self->{compute} ? $self->perform_compute
1806             : defined $self->{_migrate_from} ? $self->migrate_value
1807 2214 100       9482 : $self->{default};
    100          
    100          
    100          
1808             }
1809              
1810 21     21 1 57 sub fetch_summary ($self, @args) {
  21         38  
  21         53  
  21         36  
1811 21   100     54 my $value = $self->fetch(@args) // '<undef>';
1812 21         85 $value =~ s/\n/ /g;
1813 21 100       109 $value = substr( $value, 0, 15 ) . '...' if length($value) > 15;
1814 21         137 return $value;
1815             }
1816              
1817 8013     8013 1 33537 sub fetch ($self, @args) {
  8013         11166  
  8013         14962  
  8013         10915  
1818 8013 100       24116 my %args = @args > 1 ? @args : ( mode => $args[0] );
1819 8013   100     21531 my $mode = $args{mode} || 'backend';
1820 8013   100     24782 my $silent = $args{silent} || 0;
1821 8013         23207 my $check = $self->_check_check( $args{check} );
1822              
1823 8013 100       23925 if ( $logger->is_trace ) {
1824 69         597 $logger->trace( "called for "
1825             . $self->location
1826             . " check $check mode $mode"
1827             . " needs_check "
1828             . $self->needs_check );
1829             }
1830              
1831 8013         60080 my $inst = $self->instance;
1832              
1833 8013         19069 my $value = $self->_fetch( $mode, $check );
1834              
1835 8011 100       16431 if ( $logger->is_debug ) {
1836 69 100       388 $logger->debug( "_fetch returns " . ( defined $value ? $value : '<undef>' ) );
1837             }
1838              
1839 8011 50       41228 if ( my $err = $self->is_bad_mode($mode) ) {
1840 0         0 croak "fetch: $err";
1841             }
1842              
1843 8011 100 66     19852 if ( defined $self->{replace_follow} and defined $value ) {
1844             my $rep = $self->grab_value(
1845 4         31 step => $self->{replace_follow} . qq!:"$value"!,
1846             mode => 'loose',
1847             autoadd => 0,
1848             );
1849              
1850             # store replaced value to trigger notify_change
1851 4 100 66     18 if ( defined $rep and $rep ne $value ) {
1852 2         13 $logger->debug( "fetch replace_follow $value with $rep from ".$self->{replace_follow});
1853 2         19 $value = $self->_store_value($rep);
1854             }
1855             }
1856              
1857             # check and subsequent storage of fixes instruction must be done only
1858             # in user or custom mode. (because fixes are cleaned up during check and using
1859             # mode may not trigger the warnings. Hence confusion afterwards)
1860 8011         13189 my $ok = 1;
1861 8011 100 100     59699 $ok = $self->check( value => $value, silent => $silent, mode => $mode )
1862             if $mode =~ /backend|custom|user/ and $check ne 'no';
1863              
1864 8011 100       68072 $logger->trace( "$mode fetch (almost) done for " . $self->location )
1865             if $logger->is_trace;
1866              
1867             # check validity (all modes)
1868 8011 100 66     51700 if ( $ok or $check eq 'no' ) {
    100          
1869 7992         17686 return $self->map_write_as($value);
1870             }
1871             elsif ( $check eq 'skip' ) {
1872 1         4 my $msg = $self->error_msg;
1873 1   50     6 my $str = $value // '<undef>';
1874 1 50 33     9 $user_logger->warn("Warning: fetch [".$self->name,"] skipping value $str because of the following errors:\n$msg\n")
1875             if not $silent and $msg;
1876             # this method is supposed to return a scalar
1877 1         12 return undef; ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1878              
1879             }
1880              
1881             Config::Model::Exception::WrongValue->throw(
1882 18         98 object => $self,
1883             error => $self->error_msg
1884             );
1885              
1886 0         0 return;
1887             }
1888              
1889 10582     10582 0 15485 sub map_write_as ($self, @args) {
  10582         14501  
  10582         16971  
  10582         13274  
1890 10582         15042 my @res;
1891 10582 100 66     27171 if ($self->{write_as} and $self->value_type eq 'boolean') {
1892 71         172 foreach my $v (@args) {
1893 73 100 100     534 push @res, ( defined $v and $v =~ /^\d+$/ ) ? $self->{write_as}[$v] : $v;
1894             }
1895             }
1896             else {
1897 10511         20250 @res = @args;
1898             }
1899 10582 100       48711 return wantarray ? @res : $res[0];
1900             }
1901              
1902             sub user_value {
1903 0     0 1 0 return shift->{data};
1904             }
1905              
1906             sub fetch_preset {
1907 0     0 1 0 my $self = shift;
1908 0         0 return $self->map_write_as( $self->{preset} );
1909             }
1910              
1911             sub clear {
1912 4     4 1 866 my $self = shift;
1913 4         16 $self->store(undef);
1914 4         11 return;
1915             }
1916              
1917             sub clear_preset {
1918 32     32 1 55 my $self = shift;
1919 32         54 delete $self->{preset};
1920 32   66     192 return defined $self->{layered} || defined $self->{data};
1921             }
1922              
1923             sub fetch_layered {
1924 0     0 1 0 my $self = shift;
1925 0         0 return $self->map_write_as( $self->{layered} );
1926             }
1927              
1928             sub clear_layered {
1929 115     115 1 193 my $self = shift;
1930 115         212 delete $self->{layered};
1931 115   66     715 return defined $self->{preset} || defined $self->{data};
1932             }
1933              
1934 2     2 1 3 sub get ($self, @args) {
  2         2  
  2         5  
  2         4  
1935 2 50       9 my %args = @args > 1 ? @args : ( path => $args[0] );
1936 2         5 my $path = delete $args{path};
1937 2 50       6 if ($path) {
1938 0         0 Config::Model::Exception::User->throw(
1939             object => $self,
1940             message => "get() called with a value with non-empty path: '$path'"
1941             );
1942             }
1943 2         8 return $self->fetch(%args);
1944             }
1945              
1946 1     1 1 3 sub set ($self, $path, @data) {
  1         3  
  1         2  
  1         2  
  1         1  
1947 1 50       4 if ($path) {
1948 0         0 Config::Model::Exception::User->throw(
1949             object => $self,
1950             message => "set() called with a value with non-empty path: '$path'"
1951             );
1952             }
1953 1         3 return $self->store(@data);
1954             }
1955              
1956             #These methods are important when this leaf value is used as a warp
1957             #master, or a variable in a compute formula.
1958              
1959             # register a dependency, This information may be used by external
1960             # tools
1961             sub register_dependency {
1962 43     43 0 94 my $self = shift;
1963 43         84 my $slave = shift;
1964              
1965 43         66 unshift @{ $self->{depend_on_me} }, $slave;
  43         163  
1966              
1967             # weaken only applies to the passed reference, and there's no way
1968             # to duplicate a weak ref. Only a strong ref is created.
1969 43         176 weaken( $self->{depend_on_me}[0] );
1970 43         111 return;
1971             }
1972              
1973             sub get_depend_slave {
1974 1295     1295 0 2757 my $self = shift;
1975              
1976 1295         2224 my @result = ();
1977 17         41 push @result, @{ $self->{depend_on_me} }
1978 1295 100       3422 if defined $self->{depend_on_me};
1979              
1980 1295         4128 push @result, $self->get_warped_slaves;
1981              
1982             # needs to clean up weak ref to object that were destroyed
1983 1295         12159 return grep { defined $_ } @result;
  325         705  
1984             }
1985              
1986             __PACKAGE__->meta->make_immutable;
1987              
1988             1;
1989              
1990             # ABSTRACT: Strongly typed configuration value
1991              
1992             __END__
1993              
1994             =pod
1995              
1996             =encoding UTF-8
1997              
1998             =head1 NAME
1999              
2000             Config::Model::Value - Strongly typed configuration value
2001              
2002             =head1 VERSION
2003              
2004             version 2.153
2005              
2006             =head1 SYNOPSIS
2007              
2008             use Config::Model;
2009              
2010             # define configuration tree object
2011             my $model = Config::Model->new;
2012             $model ->create_config_class (
2013             name => "MyClass",
2014              
2015             element => [
2016              
2017             [qw/foo bar/] => {
2018             type => 'leaf',
2019             value_type => 'string',
2020             description => 'foobar',
2021             }
2022             ,
2023             country => {
2024             type => 'leaf',
2025             value_type => 'enum',
2026             choice => [qw/France US/],
2027             description => 'big countries',
2028             }
2029             ,
2030             ],
2031             ) ;
2032              
2033             my $inst = $model->instance(root_class_name => 'MyClass' );
2034              
2035             my $root = $inst->config_root ;
2036              
2037             # put data
2038             $root->load( steps => 'foo=FOO country=US' );
2039              
2040             print $root->report ;
2041             # foo = FOO
2042             # DESCRIPTION: foobar
2043             #
2044             # country = US
2045             # DESCRIPTION: big countries
2046              
2047             =head1 DESCRIPTION
2048              
2049             This class provides a way to specify configuration value with the
2050             following properties:
2051              
2052             =over
2053              
2054             =item *
2055              
2056             Strongly typed scalar: the value can either be an enumerated type, a boolean,
2057             a number, an integer or a string
2058              
2059             =item *
2060              
2061             default parameter: a value can have a default value specified during
2062             the construction. This default value is written in the target
2063             configuration file. (C<default> parameter)
2064              
2065             =item *
2066              
2067             upstream default parameter: specifies a default value that is
2068             used by the application when no information is provided in the
2069             configuration file. This upstream_default value is not written in
2070             the configuration files. Only the C<fetch_standard> method returns
2071             the builtin value. This parameter was previously referred as
2072             C<built_in> value. This may be used for audit
2073             purpose. (C<upstream_default> parameter)
2074              
2075             =item *
2076              
2077             mandatory value: reading a mandatory value raises an exception if the
2078             value is not specified (i.e is C<undef> or empty string) and has no
2079             default value.
2080              
2081             =item *
2082              
2083             dynamic change of property: A slave value can be registered to another
2084             master value so that the properties of the slave value can change
2085             according to the value of the master value. For instance, paper size value
2086             can be 'letter' for country 'US' and 'A4' for country 'France'.
2087              
2088             =item *
2089              
2090             A reference to the Id of a hash of list element. In other word, the
2091             value is an enumerated type where the possible values (choice) is
2092             defined by the existing keys of a has element somewhere in the tree. See
2093             L</"Value Reference">.
2094              
2095             =back
2096              
2097             =head1 Default values
2098              
2099             There are several kind of default values. They depend on where these
2100             values are defined (or found).
2101              
2102             From the lowest default level to the "highest":
2103              
2104             =over
2105              
2106             =item *
2107              
2108             C<upstream_default>: The value is known in the application, but is not
2109             written in the configuration file.
2110              
2111             =item *
2112              
2113             C<layered>: The value is known by the application through another
2114             mean (e.g. an included configuration file), but is not written in the
2115             configuration file.
2116              
2117             =item *
2118              
2119             C<default>: The value is known by the model, but not by the
2120             application. This value must be written in the configuration file.
2121              
2122             =item *
2123              
2124             C<computed>: The value is computed from other configuration
2125             elements. This value must be written in the configuration file.
2126              
2127             =item *
2128              
2129             C<preset>: The value is not known by the model or by the
2130             application. But it can be found by an automatic program and stored
2131             while the configuration L<Config::Model::Instance|instance> is in
2132             L<preset mode|Config::Model::Instance/"preset_start ()">
2133              
2134             =back
2135              
2136             Then there is the value entered by the user. This overrides all
2137             kind of "default" value.
2138              
2139             The L<fetch_standard> function returns the "highest" level of
2140             default value, but does not return a custom value, i.e. a value
2141             entered by the user.
2142              
2143             =head1 Constructor
2144              
2145             Value object should not be created directly.
2146              
2147             =head1 Value model declaration
2148              
2149             A leaf element must be declared with the following parameters:
2150              
2151             =over
2152              
2153             =item value_type
2154              
2155             Either C<boolean>, C<enum>, C<integer>, C<number>,
2156             C<uniline>, C<string>, C<file>, C<dir>. Mandatory. See L</"Value types">.
2157              
2158             =item default
2159              
2160             Specify the default value (optional)
2161              
2162             =item upstream_default
2163              
2164             Specify a built in default value (optional). I.e a value known by the application
2165             which does not need to be written in the configuration file.
2166              
2167             =item write_as
2168              
2169             Array ref. Reserved for boolean value. Specify how to write a boolean value.
2170             Default is C<[0,1]> which may not be the most readable. C<write_as> can be
2171             specified as C<['false','true']> or C<['no','yes']>.
2172              
2173             =item compute
2174              
2175             Computes a value according to a formula and other values. By default
2176             a computed value cannot be set. See L<Config::Model::ValueComputer> for
2177             computed value declaration.
2178              
2179             =item migrate_from
2180              
2181             This is a special parameter to cater for smooth configuration
2182             upgrade. This parameter can be used to copy the value of a deprecated
2183             parameter to its replacement. See L</Upgrade> for details.
2184              
2185             =item convert => [uc | lc ]
2186              
2187             When stored, the value is converted to uppercase (uc) or
2188             lowercase (lc).
2189              
2190             =item min
2191              
2192             Specify the minimum value (optional, only for integer, number)
2193              
2194             =item max
2195              
2196             Specify the maximum value (optional, only for integer, number)
2197              
2198             =item mandatory
2199              
2200             Set to 1 if the configuration value B<must> be set by the
2201             configuration user (default: 0)
2202              
2203             =item choice
2204              
2205             Array ref of the possible value of an enum. Example :
2206              
2207             choice => [ qw/foo bar/]
2208              
2209             =item match
2210              
2211             Perl regular expression. The value is matched with the regex to
2212             assert its validity. Example C<< match => '^foo' >> means that the
2213             parameter value must begin with "foo". Valid only for C<string> or
2214             C<uniline> values.
2215              
2216             =item warn_if_match
2217              
2218             Hash ref. Keys are made of Perl regular expression. The value can
2219             specify a warning message (leave empty or undefined for a default warning
2220             message) and instructions to fix the value. A warning is issued
2221             when the value matches the passed regular expression. Valid only for
2222             C<string> or C<uniline> values. The fix instructions is evaluated
2223             when L<apply_fixes> is called. C<$_> contains the value to fix.
2224             C<$_> is stored as the new value once the instructions are done.
2225             C<$self> contains the value object. Use with care.
2226              
2227             In the example below, any value matching 'foo' is converted in uppercase:
2228              
2229             warn_if_match => {
2230             'foo' => {
2231             fix => 'uc;',
2232             msg => 'value $_ contains foo'
2233             },
2234             'BAR' => {
2235             fix =>'lc;',
2236             msg => 'value $_ contains BAR'
2237             }
2238             },
2239              
2240             The tests are done in alphabetical order. In the example above, C<BAR> test is
2241             done before C<foo> test.
2242              
2243             C<$_> is substituted with the bad value when the message is generated. C<$std_value>
2244             is substituted with the standard value (i.e the preset, computed or default value).
2245              
2246             =item warn_unless_match
2247              
2248             Hash ref like above. A warning is issued when the value does not
2249             match the passed regular expression. Valid only for C<string> or
2250             C<uniline> values.
2251              
2252             =item warn
2253              
2254             String. Issue a warning to user with the specified string any time a value is set or read.
2255              
2256             =item warn_if
2257              
2258             A bit like C<warn_if_match>. The hash key is not a regexp but a label to
2259             help users. The hash ref contains some Perl code that is evaluated to
2260             perform the test. A warning is issued if the given code returns true.
2261              
2262             C<$_> contains the value to check. C<$self> contains the
2263             C<Config::Model::Value> object (use with care).
2264              
2265             The example below warns if value contains a number:
2266              
2267             warn_if => {
2268             warn_test => {
2269             code => 'defined $_ && /\d/;',
2270             msg => 'value $_ should not have numbers',
2271             fix => 's/\d//g;'
2272             }
2273             },
2274              
2275             Hash key is used in warning message when C<msg> is not set:
2276              
2277             warn_if => {
2278             'should begin with foo' => {
2279             code => 'defined && /^foo/'
2280             }
2281             }
2282              
2283             Any operation or check on file must be done with C<file> sub
2284             (otherwise tests will break). This sub returns a L<Path::Tiny>
2285             object that can be used to perform checks. For instance:
2286              
2287             warn_if => {
2288             warn_test => {
2289             code => 'not file($_)->exists',
2290             msg => 'file $_ should exist'
2291             }
2292              
2293             =item warn_unless
2294              
2295             Like C<warn_if>, but issue a warning when the given C<code> returns false.
2296              
2297             The example below warns unless the value points to an existing directory:
2298              
2299             warn_unless => {
2300             'missing dir' => {
2301             code => '-d',
2302             fix => "system(mkdir $_);" }
2303             }
2304              
2305             =item assert
2306              
2307             Like C<warn_if>. Except that returned value triggers an error when the
2308             given code returns false:
2309              
2310             assert => {
2311             test_nb => {
2312             code => 'defined $_ && /\d/;',
2313             msg => 'should not have numbers',
2314             fix => 's/\d//g;'
2315             }
2316             },
2317              
2318             hash key can also be used to generate error message when C<msg> parameter is not set.
2319              
2320             =item grammar
2321              
2322             Setup a L<Parse::RecDescent> grammar to perform validation.
2323              
2324             If the grammar does not start with a "check" rule (i.e does not start with "check: "),
2325             the first line of the grammar is modified to add "check" rule and this rules is set up so
2326             the entire value must match the passed grammar.
2327              
2328             I.e. the grammar:
2329              
2330             token (oper token)(s?)
2331             oper: 'and' | 'or'
2332             token: 'Apache' | 'CC-BY' | 'Perl'
2333              
2334             is changed to
2335              
2336             check: token (oper token)(s?) /^\Z/ {$return = 1;}
2337             oper: 'and' | 'or'
2338             token: 'Apache' | 'CC-BY' | 'Perl'
2339              
2340             The rule is called with Value object and a string reference. So, in the
2341             actions you may need to define, you can call the value object as
2342             C<$arg[0]>, store error message in C<${$arg[1]}}> and store warnings in
2343             C<${$arg[2]}}>.
2344              
2345             =item replace
2346              
2347             Hash ref. Used for enum to substitute one value with another. This
2348             parameter must be used to enable user to upgrade a configuration with
2349             obsolete values. For instance, if the value C<foo> is obsolete and
2350             replaced by C<foo_better>, you must declare:
2351              
2352             replace => { foo => 'foo_better' }
2353              
2354             The hash key can also be a regular expression for wider range replacement.
2355             The regexp must match the whole value:
2356              
2357             replace => ( 'foo.*' => 'better_foo' }
2358              
2359             In this case, a value is replaced by C<better_foo> when the
2360             C</^foo.*$/> regexp matches.
2361              
2362             =item replace_follow
2363              
2364             Path specifying a hash of value element in the configuration tree. The
2365             hash if used in a way similar to the C<replace> parameter. In this case, the
2366             replacement is not coded in the model but specified by the configuration.
2367              
2368             =item refer_to
2369              
2370             Specify a path to an id element used as a reference. See L<Value
2371             Reference> for details.
2372              
2373             =item computed_refer_to
2374              
2375             Specify a path to an id element used as a computed reference. See
2376             L<Value Reference> for details.
2377              
2378             =item warp
2379              
2380             See section below: L</"Warp: dynamic value configuration">.
2381              
2382             =item help
2383              
2384             You may provide detailed description on possible values with a hash
2385             ref. Example:
2386              
2387             help => { oui => "French for 'yes'", non => "French for 'no'"}
2388              
2389             The key of help is used as a regular expression to find the help text
2390             applicable to a value. These regexp are tried from the longest to the
2391             shortest and are matched from the beginning of the string. The key "C<.>"
2392             or "C<.*>" are fallback used last.
2393              
2394             For instance:
2395              
2396             help => {
2397             'foobar' => 'help for values matching /^foobar/',
2398             'foo' => 'help for values matching /^foo/ but not /^foobar/ (used above)',
2399             '.' => 'help for all other values'
2400             }
2401              
2402             =back
2403              
2404             =head2 Value types
2405              
2406             This modules can check several value types:
2407              
2408             =over
2409              
2410             =item C<boolean>
2411              
2412             Accepts values C<1> or C<0>, C<yes> or C<no>, C<true> or C<false>, and
2413             empty string. The value read back is always C<1> or C<0>.
2414              
2415             =item C<enum>
2416              
2417             Enum choices must be specified by the C<choice> parameter.
2418              
2419             =item C<integer>
2420              
2421             Enable positive or negative integer
2422              
2423             =item C<number>
2424              
2425             The value can be a decimal number
2426              
2427             =item C<uniline>
2428              
2429             A one line string. I.e without "\n" in it.
2430              
2431             =item C<string>
2432              
2433             Actually, no check is performed with this type.
2434              
2435             =item C<reference>
2436              
2437             Like an C<enum> where the possible values (aka choice) is defined by
2438             another location if the configuration tree. See L</Value Reference>.
2439              
2440             =item C<file>
2441              
2442             A file name or path. A warning is issued if the file does not
2443             exists (or is a directory)
2444              
2445             =item C<dir>
2446              
2447             A directory name or path. A warning is issued if the directory
2448             does not exists (or is a plain file)
2449              
2450             =back
2451              
2452             =head1 Warp: dynamic value configuration
2453              
2454             The Warp functionality enable a C<Value> object to change its
2455             properties (i.e. default value or its type) dynamically according to
2456             the value of another C<Value> object locate elsewhere in the
2457             configuration tree. (See L<Config::Model::Warper> for an
2458             explanation on warp mechanism).
2459              
2460             For instance if you declare 2 C<Value> element this way:
2461              
2462             $model ->create_config_class (
2463             name => "TV_config_class",
2464             element => [
2465             country => {
2466             type => 'leaf',
2467             value_type => 'enum',
2468             choice => [qw/US Europe Japan/]
2469             } ,
2470             tv_standard => { # this example is getting old...
2471             type => 'leaf',
2472             value_type => 'enum',
2473             choice => [ qw/PAL NTSC SECAM/ ]
2474             warp => {
2475             follow => {
2476             # this points to the warp master
2477             c => '- country'
2478             },
2479             rules => {
2480             '$c eq "US"' => {
2481             default => 'NTSC'
2482             },
2483             '$c eq "France"' => {
2484             default => 'SECAM'
2485             },
2486             '$c eq "Japan"' => {
2487             default => 'NTSC'
2488             },
2489             '$c eq "Europe"' => {
2490             default => 'PAL'
2491             },
2492             }
2493             }
2494             } ,
2495             ]
2496             );
2497              
2498             Setting C<country> element to C<US> means that C<tv_standard> has
2499             a default value set to C<NTSC> by the warp mechanism.
2500              
2501             Likewise, the warp mechanism enables you to dynamically change the
2502             possible values of an enum element:
2503              
2504             state => {
2505             type => 'leaf',
2506             value_type => 'enum', # example is admittedly silly
2507             warp => {
2508             follow => {
2509             c => '- country'
2510             },
2511             rules => {
2512             '$c eq "US"' => {
2513             choice => ['Kansas', 'Texas' ]
2514             },
2515             '$c eq "Europe"' => {
2516             choice => ['France', 'Spain' ]
2517             },
2518             '$c eq "Japan"' => {
2519             choice => ['Honshu', 'Hokkaido' ]
2520             }
2521             }
2522             }
2523             }
2524              
2525             =head2 Cascaded warping
2526              
2527             Warping value can be cascaded: C<A> can be warped by C<B> which can be
2528             warped by C<C>. But this feature should be avoided since it can lead
2529             to a model very hard to debug. Bear in mind that:
2530              
2531             =over
2532              
2533             =item *
2534              
2535             Warp loops are not detected and end up in "deep recursion
2536             subroutine" failures.
2537              
2538             =item *
2539              
2540             avoid "diamond" shaped warp dependencies: the results depends on the
2541             order of the warp algorithm which can be unpredictable in this case
2542              
2543             =item *
2544              
2545             The keys declared in the warp rules (C<US>, C<Europe> and C<Japan> in
2546             the example above) cannot be checked at start time against the warp
2547             master C<Value>. So a wrong warp rule key is silently ignored
2548             during start up and fails at run time.
2549              
2550             =back
2551              
2552             =head1 Value Reference
2553              
2554             To set up an enumerated value where the possible choice depends on the
2555             key of a L<Config::Model::AnyId> object, you must:
2556              
2557             =over
2558              
2559             =item *
2560              
2561             Set C<value_type> to C<reference>.
2562              
2563             =item *
2564              
2565             Specify the C<refer_to> or C<computed_refer_to> parameter.
2566             See L<refer_to parameter|Config::Model::IdElementReference/"Config class parameters">.
2567              
2568             =back
2569              
2570             In this case, a C<IdElementReference> object is created to handle the
2571             relation between this value object and the referred Id. See
2572             L<Config::Model::IdElementReference> for details.
2573              
2574             =head1 Introspection methods
2575              
2576             The following methods returns the current value of the parameter of
2577             the value object (as declared in the model unless they were warped):
2578              
2579             =over
2580              
2581             =item min
2582              
2583             =item max
2584              
2585             =item mandatory
2586              
2587             =item choice
2588              
2589             =item convert
2590              
2591             =item value_type
2592              
2593             =item default
2594              
2595             =item upstream_default
2596              
2597             =item index_value
2598              
2599             =item element_name
2600              
2601             =back
2602              
2603             =head2 name
2604              
2605             Returns the object name.
2606              
2607             =head2 get_type
2608              
2609             Returns C<leaf>.
2610              
2611             =head2 can_store
2612              
2613             Returns true if the value object can be assigned to. Return 0 for a
2614             read-only value (i.e. a computed value with no override allowed).
2615              
2616             =head2 get_choice
2617              
2618             Query legal values (only for enum types). Return an array (possibly
2619             empty).
2620              
2621             =head2 get_help
2622              
2623             With a parameter, returns the help string applicable to the passed
2624             value or undef.
2625              
2626             Without parameter returns a hash ref that contains all the help strings.
2627              
2628             =head2 get_info
2629              
2630             Returns a list of information related to the value, like value type,
2631             default value. This should be used to provide some debug information
2632             to the user.
2633              
2634             For instance, C<$val->get-info> may return:
2635              
2636             [ 'type: string', 'mandatory: yes' ]
2637              
2638             =head2 error_msg
2639              
2640             Returns the error messages of this object (if any)
2641              
2642             =head2 warning_msg
2643              
2644             Returns warning concerning this value. Returns a list in list
2645             context and a string in scalar context.
2646              
2647             =head2 check_value
2648              
2649             Parameters: C<< ( value ) >>
2650              
2651             Check the consistency of the value.
2652              
2653             C<check_value> also accepts named parameters:
2654              
2655             =over 4
2656              
2657             =item value
2658              
2659             =item quiet
2660              
2661             When non null, check does not try to get extra
2662             information from the tree. This is required in some cases to avoid
2663             loops in check, get_info, get_warp_info, re-check ...
2664              
2665             =back
2666              
2667             In scalar context, return 0 or 1.
2668              
2669             In array context, return an empty array when no error was found. In
2670             case of errors, returns an array of error strings that should be shown
2671             to the user.
2672              
2673             =head2 has_fixes
2674              
2675             Returns the number of fixes that can be applied to the current value.
2676              
2677             =head2 apply_fixes
2678              
2679             Applies the fixes to suppress the current warnings.
2680              
2681             =head2 check
2682              
2683             Parameters: C<< ( [ value => foo ] ) >>
2684              
2685             Like L</check_value>.
2686              
2687             Also displays warnings on STDOUT unless C<silent> parameter is set to 1.
2688             In this case,user is expected to retrieve them with
2689             L</warning_msg>.
2690              
2691             Without C<value> argument, this method checks the value currently stored.
2692              
2693             =head2 is_bad_mode
2694              
2695             Accept a mode parameter. This function checks if the mode is accepted
2696             by L</fetch> method. Returns an error message if not. For instance:
2697              
2698             if (my $err = $val->is_bad_mode('foo')) {
2699             croak "my_function: $err";
2700             }
2701              
2702             This method is intented as a helper to avoid duplicating the list of
2703             accepted modes for functions that want to wrap fetch methods (like
2704             L<Config::Model::Dumper> or L<Config::Model::DumpAsData>)
2705              
2706             =head1 Information management
2707              
2708             =head2 store
2709              
2710             Parameters: C<< ( $value ) >>
2711             or C<< value => ..., check => yes|no|skip ), silent => 0|1 >>
2712              
2713             Store value in leaf element. C<check> parameter can be used to
2714             skip validation check (default is 'yes').
2715             C<silent> can be used to suppress warnings.
2716              
2717             Optional C<callback> is now deprecated.
2718              
2719             =head2 clear
2720              
2721             Clear the stored value. Further read returns the default value (or
2722             computed or migrated value).
2723              
2724             =head2 load_data
2725              
2726             Parameters: C<< ( $value ) >>
2727              
2728             Called with the same parameters are C<store> method.
2729              
2730             Load scalar data. Data is forwarded to L</"store"> after checking that
2731             the passed value is not a reference.
2732              
2733             =head2 fetch_custom
2734              
2735             Returns the stored value if this value is different from a standard
2736             setting or built in setting. In other words, returns undef if the
2737             stored value is identical to the default value or the computed value
2738             or the built in value.
2739              
2740             =head2 fetch_standard
2741              
2742             Returns the standard value as defined by the configuration model. The
2743             standard value can be either a preset value, a layered value, a computed value, a
2744             default value or a built-in default value.
2745              
2746             =head2 has_data
2747              
2748             Return true if the value contains information different from default
2749             or upstream default value.
2750              
2751             =head2 fetch
2752              
2753             Check and fetch value from leaf element. The method can have one parameter (the fetch mode)
2754             or several pairs:
2755              
2756             =over 4
2757              
2758             =item mode
2759              
2760             Whether to fetch default, custom, etc value. See below for details
2761              
2762             =item check
2763              
2764             Whether to check if the value is valid or not before returning it. Default is 'yes'.
2765             Possible value are
2766              
2767             =over 4
2768              
2769             =item yes
2770              
2771             Perform check and raise an exception for bad values
2772              
2773             =item skip
2774              
2775             Perform check and return undef for bad values. A warning is issued when a bad value is skipped.
2776             Set C<check> to C<no> to avoid warnings.
2777              
2778             =item no
2779              
2780             Do not check and return values even if bad
2781              
2782             =back
2783              
2784             =item silent
2785              
2786             When set to 1, warning are not displayed on STDOUT. User is expected to read warnings
2787             with L<warning_msg> method.
2788              
2789             =back
2790              
2791             According to the C<mode> parameter, this method returns either:
2792              
2793             =over
2794              
2795             =item empty mode parameter (default)
2796              
2797             Value entered by user or default value if the value is different from upstream_default or
2798             layered value. Typically this value is written in a configuration file.
2799              
2800             =item backend
2801              
2802             Alias for default mode.
2803              
2804             =item custom
2805              
2806             The value entered by the user (if different from built in, preset,
2807             computed or default value)
2808              
2809             =item user
2810              
2811             The value most useful to user: the value that is used by the application.
2812              
2813             =item preset
2814              
2815             The value entered in preset mode
2816              
2817             =item standard
2818              
2819             The preset or computed or default or built in value.
2820              
2821             =item default
2822              
2823             The default value (defined by the configuration model)
2824              
2825             =item layered
2826              
2827             The value found in included files (treated in layered mode: values specified
2828             there are handled as upstream default values). E.g. like in multistrap config.
2829              
2830             =item upstream_default
2831              
2832             The upstream_default value. (defined by the configuration model)
2833              
2834             =item non_upstream_default
2835              
2836             The custom or preset or computed or default value. Returns undef
2837             if either of this value is identical to the upstream_default value. This
2838             feature is useful to reduce data to write in configuration file.
2839              
2840             =item allow_undef
2841              
2842             With this mode, C<fetch()> behaves like in C<user> mode, but returns
2843             C<undef> for mandatory values. Normally, trying to fetch an undefined
2844             mandatory value leads to an exception.
2845              
2846             =back
2847              
2848             =head2 fetch_summary
2849              
2850             Returns a truncated value when the value is a string or uniline that
2851             is too long to be displayed.
2852              
2853             =head2 user_value
2854              
2855             Returns the value entered by the user. Does not use the default or
2856             computed value. Returns undef unless a value was actually stored.
2857              
2858             =head2 fetch_preset
2859              
2860             Returns the value entered in preset mode. Does not use the default or
2861             computed value. Returns undef unless a value was actually stored in
2862             preset mode.
2863              
2864             =head2 clear_preset
2865              
2866             Delete the preset value. (Even out of preset mode). Returns true if other data
2867             are still stored in the value (layered or user data). Returns false otherwise.
2868              
2869             =head2 fetch_layered
2870              
2871             Returns the value entered in layered mode. Does not use the default or
2872             computed value. Returns undef unless a value was actually stored in
2873             layered mode.
2874              
2875             =head2 clear_layered
2876              
2877             Delete the layered value. (Even out of layered mode). Returns true if other data
2878             are still stored in the value (layered or user data). Returns false otherwise.
2879              
2880             =head2 get( path => ..., mode => ... , check => ... )
2881              
2882             Get a value from a directory like path.
2883              
2884             =head2 set( path , value )
2885              
2886             Set a value from a directory like path.
2887              
2888             =head1 Examples
2889              
2890             =head2 Number with min and max values
2891              
2892             bounded_number => {
2893             type => 'leaf',
2894             value_type => 'number',
2895             min => 1,
2896             max => 4,
2897             },
2898              
2899             =head2 Mandatory value
2900              
2901             mandatory_string => {
2902             type => 'leaf',
2903             value_type => 'string',
2904             mandatory => 1,
2905             },
2906              
2907             mandatory_boolean => {
2908             type => 'leaf',
2909             value_type => 'boolean',
2910             mandatory => 1,
2911             },
2912              
2913             =head2 Enum with help associated with each value
2914              
2915             Note that the help specification is optional.
2916              
2917             enum_with_help => {
2918             type => 'leaf',
2919             value_type => 'enum',
2920             choice => [qw/a b c/],
2921             help => {
2922             a => 'a help'
2923             }
2924             },
2925              
2926             =head2 Migrate old obsolete enum value
2927              
2928             Legacy values C<a1>, C<c1> and C<foo/.*> are replaced with C<a>, C<c> and C<foo/>.
2929              
2930             with_replace => {
2931             type => 'leaf',
2932             value_type => 'enum',
2933             choice => [qw/a b c/],
2934             replace => {
2935             a1 => 'a',
2936             c1 => 'c',
2937             'foo/.*' => 'foo',
2938             },
2939             },
2940              
2941             =head2 Enforce value to match a regexp
2942              
2943             An exception is triggered when the value does not match the C<match>
2944             regular expression.
2945              
2946             match => {
2947             type => 'leaf',
2948             value_type => 'string',
2949             match => '^foo\d{2}$',
2950             },
2951              
2952             =head2 Enforce value to match a L<Parse::RecDescent> grammar
2953              
2954             match_with_parse_recdescent => {
2955             type => 'leaf',
2956             value_type => 'string',
2957             grammar => q{
2958             token (oper token)(s?)
2959             oper: 'and' | 'or'
2960             token: 'Apache' | 'CC-BY' | 'Perl'
2961             },
2962             },
2963              
2964             =head2 Issue a warning if a value matches a regexp
2965              
2966             Issue a warning if the string contains upper case letters. Propose a fix that
2967             translate all capital letters to lower case.
2968              
2969             warn_if_capital => {
2970             type => 'leaf',
2971             value_type => 'string',
2972             warn_if_match => {
2973             '/A-Z/' => {
2974             fix => '$_ = lc;'
2975             }
2976             },
2977             },
2978              
2979             A specific warning can be specified:
2980              
2981             warn_if_capital => {
2982             type => 'leaf',
2983             value_type => 'string',
2984             warn_if_match => {
2985             '/A-Z/' => {
2986             fix => '$_ = lc;',
2987             mesg => 'NO UPPER CASE PLEASE'
2988             }
2989             },
2990             },
2991              
2992             =head2 Issue a warning if a value does NOT match a regexp
2993              
2994             warn_unless => {
2995             type => 'leaf',
2996             value_type => 'string',
2997             warn_unless_match => {
2998             foo => {
2999             msg => '',
3000             fix => '$_ = "foo".$_;'
3001             }
3002             },
3003             },
3004              
3005             =head2 Always issue a warning
3006              
3007             always_warn => {
3008             type => 'leaf',
3009             value_type => 'string',
3010             warn => 'Always warn whenever used',
3011             },
3012              
3013             =head2 Computed values
3014              
3015             See L<Config::Model::ValueComputer/Examples>.
3016              
3017             =head1 Upgrade
3018              
3019             Upgrade is a special case when the configuration of an application has
3020             changed. Some parameters can be removed and replaced by another
3021             one. To avoid trouble on the application user side, Config::Model
3022             offers a possibility to handle the migration of configuration data
3023             through a special declaration in the configuration model.
3024              
3025             This declaration must:
3026              
3027             =over
3028              
3029             =item *
3030              
3031             Declare the deprecated parameter with a C<status> set to C<deprecated>
3032              
3033             =item *
3034              
3035             Declare the new parameter with the instructions to load the semantic
3036             content from the deprecated parameter. These instructions are declared
3037             in the C<migrate_from> parameters (which is similar to the C<compute>
3038             parameter)
3039              
3040             =back
3041              
3042             Here an example where a URL parameter is changed to a set of 2
3043             parameters (host and path):
3044              
3045             'old_url' => {
3046             type => 'leaf',
3047             value_type => 'uniline',
3048             status => 'deprecated',
3049             },
3050             'host' => {
3051             type => 'leaf',
3052             value_type => 'uniline',
3053              
3054             # the formula must end with '$1' so the result of the capture is used
3055             # as the host value
3056             migrate_from => {
3057             formula => '$old =~ m!http://([\w\.]+)!; $1 ;',
3058             variables => {
3059             old => '- old_url'
3060             },
3061             use_eval => 1,
3062             },
3063             },
3064             'path' => {
3065             type => 'leaf',
3066             value_type => 'uniline',
3067             migrate_from => {
3068             formula => '$old =~ m!http://[\w\.]+(/.*)!; $1 ;',
3069             variables => {
3070             old => '- old_url'
3071             },
3072             use_eval => 1,
3073             },
3074             },
3075              
3076             =head1 EXCEPTION HANDLING
3077              
3078             When an error is encountered, this module may throw the following
3079             exceptions:
3080              
3081             Config::Model::Exception::Model
3082             Config::Model::Exception::Formula
3083             Config::Model::Exception::WrongValue
3084             Config::Model::Exception::WarpError
3085              
3086             See L<Config::Model::Exception> for more details.
3087              
3088             =head1 AUTHOR
3089              
3090             Dominique Dumont, (ddumont at cpan dot org)
3091              
3092             =head1 SEE ALSO
3093              
3094             L<Config::Model>, L<Config::Model::Node>,
3095             L<Config::Model::AnyId>, L<Config::Model::Warper>, L<Config::Model::Exception>
3096             L<Config::Model::ValueComputer>,
3097              
3098             =head1 AUTHOR
3099              
3100             Dominique Dumont
3101              
3102             =head1 COPYRIGHT AND LICENSE
3103              
3104             This software is Copyright (c) 2005-2022 by Dominique Dumont.
3105              
3106             This is free software, licensed under:
3107              
3108             The GNU Lesser General Public License, Version 2.1, February 1999
3109              
3110             =cut