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 |