1Config::Model::ValueComUpsuetrerC(o3nptmr)ibuted Perl DoCcounmfeingt:a:tMioodnel::ValueComputer(3pm)
2
3
4
6 Config::Model::ValueComputer - Provides configuration value computation
7
9 version 2.153
10
12 use Config::Model;
13
14 # define configuration tree object
15 my $model = Config::Model->new;
16 $model ->create_config_class (
17 name => "MyClass",
18
19 element => [
20 [qw/av bv/] => {
21 type => 'leaf',
22 value_type => 'integer',
23 },
24 compute_int => {
25 type => 'leaf',
26 value_type => 'integer',
27 compute => {
28 formula => '$a + $b',
29 variables => { a => '- av', b => '- bv'}
30 },
31 },
32 ],
33 );
34
35 my $inst = $model->instance(root_class_name => 'MyClass' );
36
37 my $root = $inst->config_root ;
38
39 # put data
40 $root->load( steps => 'av=33 bv=9' );
41
42 print "Computed value is ",$root->grab_value('compute_int'),"\n";
43 # Computed value is 42
44
46 This class provides a way to compute a configuration value. This
47 computation uses a formula and some other configuration values from the
48 configuration tree.
49
50 The computed value can be overridden, in other words, the computed
51 value can be used as a default value.
52
54 A computed value must be declared in a 'leaf' element. The leaf element
55 must have a "compute" argument pointing to a hash ref.
56
57 This array ref contains:
58
59 • A string formula that use variables and replace function.
60
61 • A set of variable and their relative location in the tree (using
62 the notation explained in grab method
63
64 • An optional set of replace rules.
65
66 • An optional parameter to force a Perl eval of a string.
67
68 Note: A variable must point to a valid location in the configuration
69 tree. Even when &index() or "$replace{}" is used. After substitution of
70 these functions, the string is used as a path (See grab) starting from
71 the computed value. Hence the path must begin with "!" to go back to
72 root node, or "-" to go up a level.
73
74 Compute formula
75 The first element of the "compute" array ref must be a string that
76 contains the computation algorithm (i.e. a formula for arithmetic
77 computation for integer values or a string template for string values).
78
79 This string or formula should contain variables (like $foo or $bar).
80 Note that these variables are not interpolated by Perl.
81
82 For instance:
83
84 'My cat has $nb legs'
85 '$m * $c**2'
86
87 This string or formula may also contain:
88
89 • The index value of the current object : &index or &index().
90
91 • The index value of a parent object: &index(-). Ancestor index value
92 can be retrieved with &index(-2) or &index(-3) or "&index(- -)" or
93 "&index(- - -)"
94
95 • The element name of the current object: &element or &element().
96
97 • The element name of a parent object: &element(-). Likewise,
98 ancestor element name can be retrieved with &element(-2) or
99 &element(-3).
100
101 • The full location (path) of the current object: &location or
102 &location().
103
104 For instance, you could have this template string:
105
106 'my element is &element, my index is &index' .
107 'upper element is &element(-), upper index is &index(-)',
108
109 If you need to perform more complex operations than substitution, like
110 extraction with regular expressions, you can force an eval done by Perl
111 with "use_eval => 1". In this case, the result of the eval is used as
112 the computed value.
113
114 For instance:
115
116 # extract host from url
117 compute => {
118 formula => '$old =~ m!http://[\w\.]+(?::\d+)?(/.*)!; $1 ;',
119 variables => { old => '- url' } ,
120 use_eval => 1 ,
121 },
122
123 # capitalize
124 compute => {
125 formula => 'uc($old)',
126 variables => { old => '- small_caps' } ,
127 use_eval => 1
128 }
129
130 Compute variables
131 Compute variables are a set of "key => value" pairs that define the
132 variables used in the specified formula. The key is a variable name
133 used in the string that represents the formula. The value is a string
134 that is used to get the correct Value object.
135
136 In this numeric example, "result" default value is "av + bv":
137
138 element => [
139 av => {
140 type => 'leaf',
141 value_type => 'integer'
142 },
143 bv => {
144 type => 'leaf',
145 value_type => 'integer'
146 },
147 result => {
148 type => 'leaf',
149 value_type => 'integer',
150 compute => {
151 formula => '$a + $b' ,
152 variables => { a => '- av', b => '- bv' },
153 }
154 }
155 ]
156
157 In this string example, the default value of the "Comp" element is
158 actually a string made of ""macro is "" and the value of the ""macro""
159 element of the object located 2 nodes above:
160
161 comp => {
162 type => 'leaf',
163 value_type => 'string',
164 compute => {
165 formula => '"macro is $m"' ,
166 variables => { m => '- - macro' }
167 }
168 }
169
170 Compute replace
171 Sometime, using the value of a tree leaf is not enough and you need to
172 substitute a replacement for any value you can get. This replacement
173 can be done using a hash like notation within the formula using the
174 %replace hash.
175
176 For instance, if you want to display a summary of a config, you can do
177 :
178
179 compute_with_replace => {
180 formula => '$replace{$who} is the $replace{$what} of $replace{$country}',
181 variables => {
182 who => '! who' ,
183 what => '! what' ,
184 country => '- country',
185 },
186 replace => {
187 chief => 'president',
188 America => 'USA'
189 }
190 }
191
192 Complex formula
193 &index, &element, and replace can be combined. But the argument of
194 &element or &index can only be a value object specification (I.e.
195 something like '"- - foo"'), it cannot be a value replacement of
196 another &element or &index.
197
198 I.e. &element($foo) is ok, but "&element(&index($foo))" is not allowed.
199
200 computed variable
201 Compute variables can themselves be computed :
202
203 compute => {
204 formula => 'get_element is $replace{$s}, indirect value is \'$v\'',
205 variables => {
206 s => '! $where',
207 where => '! where_is_element',
208 v => '! $replace{$s}',
209 }
210 replace => {
211 m_value_element => 'm_value',
212 compute_element => 'compute'
213 }
214 }
215
216 Be sure not to specify a loop when doing recursive computation.
217
218 The function &index &element and &location are also allowed.
219
220 compute override
221 In some case, a computed value must be interpreted as a default value
222 and the user must be able to override this computed default value. In
223 this case, you must use "allow_override => 1" with the compute
224 parameter:
225
226 computed_value_with_override => {
227 type => 'leaf',
228 value_type => 'string',
229 compute => {
230 formula => '"macro is $m"' ,
231 variables => { m => '- - macro' } ,
232 allow_override => 1,
233 }
234 }
235
236 This computed default value is written to the configuration file.
237
238 This default value may be already known by the application so the
239 computed value should not be written to the configuration file. The
240 computed value is interesting because it cab be shown to the user. In
241 this case, use the "use_as_upstream_default" parameter:
242
243 compute_known_upstream => {
244 type => 'leaf',
245 value_type => 'string',
246 compute => {
247 formula => '"macro is $m"' ,
248 variables => { m => '- - macro' } ,
249 use_as_upstream_default => 1,
250 }
251 }
252
253 "use_as_upstream_default" implies "allow_override".
254
255 Undefined variables
256 You may need to compute value where one of the variables (i.e. other
257 configuration parameter) is undefined. By default, any formula yields
258 an undefined value if one variable is undefined.
259
260 You may change this behavior with "undef_is" parameter. With this
261 parameter, you can specify a "fallback" value that is used in your
262 formula instead of an undefined variable.
263
264 The most useful fallback values are:
265
266 undef_is => "''", # for string values
267 undef_is => 0 , # for integers, boolean values
268
269 Example:
270
271 Source => {
272 type => 'leaf',
273 value_type => 'string',
274 mandatory => 1,
275 migrate_from => {
276 use_eval => 1,
277 formula => '$old || $older ;',
278 undef_is => "''",
279 variables => {
280 older => '- Original-Source-Location',
281 old => '- Upstream-Source'
282 }
283 },
284 },
285 [qw/Upstream-Source Original-Source-Location/] => {
286 value_type => 'string',
287 status => 'deprecated',
288 type => 'leaf'
289 }
290
292 String substitution
293 [qw/sav sbv/] => {
294 type => 'leaf',
295 value_type => 'string',
296 },
297 compute_string => {
298 type => 'leaf',
299 value_type => 'string',
300 compute => {
301 formula => 'meet $a and $b',
302 variables => { '- sav', b => '- sbv' }
303 },
304 },
305
306 Computation with on-the-fly replacement
307 compute_with_replace => {
308 type => 'leaf',
309 value_type => 'string',
310 compute => {
311 formula =>
312 '$replace{$who} is the $replace{$what} of $replace{$country}',
313 variables => {
314 who => '! who',
315 what => '! what',
316 country => '- country',
317 },
318 replace => {
319 chief => 'president',
320 America => 'USA'
321 },
322 },
323 },
324
325 Extract data from a value using a Perl regexp
326 Extract the host name from an URL:
327
328 url => {
329 type => 'leaf',
330 value_type => 'uniline'
331 },
332 extract_host_from_url => {
333 type => 'leaf',
334 value_type => 'uniline',
335 compute => {
336 formula => '$old =~ m!http://([\w\.]+)!; $1 ;',
337 variables => { old => '- url' },
338 use_eval => 1,
339 },
340 },
341
342 copy hash example
343 Copying a hash may not be useful, but the using &index() in a variable
344 can be. Here's an example where the hashes contain leaves.
345
346 The model is set up so that the content of "copy_from" is copied into
347 "copy_to" hash:
348
349 copy_from => {
350 'type' => 'hash',
351 'index_type' => 'string',
352 'cargo' => {
353 'config_class_name' => 'From',
354 'type' => 'node'
355 },
356 },
357 copy_to => {
358 'type' => 'hash',
359 'index_type' => 'string',
360 'cargo' => {
361 'type' => 'leaf',
362 'value_type' => 'uniline',
363 'compute' => {
364 'formula' => '$copied',
365 'variables' => {
366 'copied' => '- copy_from:&index()'
367 }
368 },
369 },
370 },
371
372 Hash copy is also possible when the hash contains node. Here's an
373 example where the data to be copied is stored within a node. The main
374 class has 2 hash elements:
375
376 copy_from => {
377 'type' => 'hash',
378 'index_type' => 'string',
379 'cargo' => {
380 'config_class_name' => 'From',
381 'type' => 'node'
382 },
383 },
384 copy_to => {
385 'type' => 'hash',
386 'index_type' => 'string',
387 'cargo' => {
388 'config_class_name' => 'To',
389 'type' => 'node'
390 },
391 },
392
393 The Class to copy from is quite short:
394
395 'name' => 'From',
396 'element' => [
397 name => {
398 'type' => 'leaf',
399 'value_type' => 'uniline',
400 }
401 ]
402
403 Here the class to copy to:
404
405 'name' => 'To',
406 'element' => [
407 name => {
408 'type' => 'leaf',
409 'value_type' => 'uniline',
410 'compute' => {
411 'formula' => '$copied',
412 'variables' => {
413 'copied' => '! copy_from:&index(-) name'
414 }
415 },
416 }
417 ]
418
420 Dominique Dumont, (ddumont at cpan dot org)
421
423 Config::Model, Config::Model::Instance, Config::Model::Value
424
426 Dominique Dumont
427
429 This software is Copyright (c) 2005-2022 by Dominique Dumont.
430
431 This is free software, licensed under:
432
433 The GNU Lesser General Public License, Version 2.1, February 1999
434
435
436
437perl v5.38.0 2023-07-25 Config::Model::ValueComputer(3pm)