1Config::Model::ValueComUpsuetrerC(o3n)tributed Perl DocuCmoennftiagt:i:oMnodel::ValueComputer(3)
2
3
4
6 Config::Model::ValueComputer - Provides configuration value computation
7
9 version 2.129
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
92 value can be retrieved with "&index(-2)" or "&index(-3)" or
93 "&index(- -)" or "&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
199 allowed.
200
201 computed variable
202 Compute variables can themselves be computed :
203
204 compute => {
205 formula => 'get_element is $replace{$s}, indirect value is \'$v\'',
206 variables => {
207 s => '! $where',
208 where => '! where_is_element',
209 v => '! $replace{$s}',
210 }
211 replace => {
212 m_value_element => 'm_value',
213 compute_element => 'compute'
214 }
215 }
216
217 Be sure not to specify a loop when doing recursive computation.
218
219 The function &index &element and &location are also allowed.
220
221 compute override
222 In some case, a computed value must be interpreted as a default value
223 and the user must be able to override this computed default value. In
224 this case, you must use "allow_override => 1" with the compute
225 parameter:
226
227 computed_value_with_override => {
228 type => 'leaf',
229 value_type => 'string',
230 compute => {
231 formula => '"macro is $m"' ,
232 variables => { m => '- - macro' } ,
233 allow_override => 1,
234 }
235 }
236
237 This computed default value is written to the configuration file.
238
239 This default value may be already known by the application so the
240 computed value should not be written to the configuration file. The
241 computed value is interesting because it cab be shown to the user. In
242 this case, use the "use_as_upstream_default" parameter:
243
244 compute_known_upstream => {
245 type => 'leaf',
246 value_type => 'string',
247 compute => {
248 formula => '"macro is $m"' ,
249 variables => { m => '- - macro' } ,
250 use_as_upstream_default => 1,
251 }
252 }
253
254 "use_as_upstream_default" implies "allow_override".
255
256 Undefined variables
257 You may need to compute value where one of the variables (i.e. other
258 configuration parameter) is undefined. By default, any formula yields
259 an undefined value if one variable is undefined.
260
261 You may change this behavior with "undef_is" parameter. With this
262 parameter, you can specify a "fallback" value that is used in your
263 formula instead of an undefined variable.
264
265 The most useful fallback values are:
266
267 undef_is => "''", # for string values
268 undef_is => 0 , # for integers, boolean values
269
270 Example:
271
272 Source => {
273 type => 'leaf',
274 value_type => 'string',
275 mandatory => 1,
276 migrate_from => {
277 use_eval => 1,
278 formula => '$old || $older ;',
279 undef_is => "''",
280 variables => {
281 older => '- Original-Source-Location',
282 old => '- Upstream-Source'
283 }
284 },
285 },
286 [qw/Upstream-Source Original-Source-Location/] => {
287 value_type => 'string',
288 status => 'deprecated',
289 type => 'leaf'
290 }
291
293 String substitution
294 [qw/sav sbv/] => {
295 type => 'leaf',
296 value_type => 'string',
297 },
298 compute_string => {
299 type => 'leaf',
300 value_type => 'string',
301 compute => {
302 formula => 'meet $a and $b',
303 variables => { '- sav', b => '- sbv' }
304 },
305 },
306
307 Computation with on-the-fly replacement
308 compute_with_replace => {
309 type => 'leaf',
310 value_type => 'string',
311 compute => {
312 formula =>
313 '$replace{$who} is the $replace{$what} of $replace{$country}',
314 variables => {
315 who => '! who',
316 what => '! what',
317 country => '- country',
318 },
319 replace => {
320 chief => 'president',
321 America => 'USA'
322 },
323 },
324 },
325
326 Extract data from a value using a Perl regexp
327 Extract the host name from an URL:
328
329 url => {
330 type => 'leaf',
331 value_type => 'uniline'
332 },
333 extract_host_from_url => {
334 type => 'leaf',
335 value_type => 'uniline',
336 compute => {
337 formula => '$old =~ m!http://([\w\.]+)!; $1 ;',
338 variables => { old => '- url' },
339 use_eval => 1,
340 },
341 },
342
343 simple copy hash example
344 Copying a hash may not be useful, but the using "&index()" in a
345 variable can be. Here's an example where the hashes contain leaves.
346
347 The model is set up so that the content of "copy_from" is copied into
348 "copy_to" hash:
349
350 copy_from => {
351 'type' => 'hash',
352 'index_type' => 'string',
353 'cargo' => {
354 'config_class_name' => 'From',
355 'type' => 'node'
356 },
357 },
358 copy_to => {
359 'type' => 'hash',
360 'index_type' => 'string',
361 'cargo' => {
362 'type' => 'leaf',
363 'value_type' => 'uniline',
364 'compute' => {
365 'formula' => '$copied',
366 'variables' => {
367 'copied' => '- copy_from:&index()'
368 }
369 },
370 },
371 },
372
373 Hash copy is also possible when the hash contains node. Here's an
374 example where the data to be copied is stored within a node. The main
375 class has 2 hash elements:
376
377 copy_from => {
378 'type' => 'hash',
379 'index_type' => 'string',
380 'cargo' => {
381 'config_class_name' => 'From',
382 'type' => 'node'
383 },
384 },
385 copy_to => {
386 'type' => 'hash',
387 'index_type' => 'string',
388 'cargo' => {
389 'config_class_name' => 'To',
390 'type' => 'node'
391 },
392 },
393
394 The Class to copy from is quite simple:
395
396 'name' => 'From',
397 'element' => [
398 name => {
399 'type' => 'leaf',
400 'value_type' => 'uniline',
401 }
402 ]
403
404 Here the class to copy to:
405
406 'name' => 'To',
407 'element' => [
408 name => {
409 'type' => 'leaf',
410 'value_type' => 'uniline',
411 'compute' => {
412 'formula' => '$copied',
413 'variables' => {
414 'copied' => '! copy_from:&index(-) name'
415 }
416 },
417 }
418 ]
419
421 Dominique Dumont, (ddumont at cpan dot org)
422
424 Config::Model, Config::Model::Instance, Config::Model::Value
425
427 Dominique Dumont
428
430 This software is Copyright (c) 2005-2018 by Dominique Dumont.
431
432 This is free software, licensed under:
433
434 The GNU Lesser General Public License, Version 2.1, February 1999
435
436
437
438perl v5.28.1 2018-12-07 Config::Model::ValueComputer(3)