File Coverage

blib/lib/Config/Model/Instance.pm
Criterion Covered Total %
statement 211 251 84.0
branch 48 80 60.0
condition 35 54 64.8
subroutine 51 59 86.4
pod 23 29 79.3
total 368 473 77.8


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::Instance 2.153; # TRIAL
11              
12             #use Scalar::Util qw(weaken) ;
13 59     59   471 use strict;
  59         176  
  59         2234  
14              
15 59     59   797 use 5.10.1;
  59         238  
16 59     59   379 use Mouse;
  59         157  
  59         575  
17 59     59   30270 use Mouse::Util::TypeConstraints;
  59         202  
  59         619  
18 59     59   7270 use MouseX::StrictConstructor;
  59         225  
  59         498  
19             with "Config::Model::Role::NodeLoader";
20              
21 59     59   13277 use File::Path;
  59         172  
  59         4741  
22 59     59   50266 use Path::Tiny;
  59         826969  
  59         3966  
23 59     59   605 use Log::Log4perl qw(get_logger :levels);
  59         173  
  59         484  
24              
25 59     59   35129 use Config::Model::TypeConstraints;
  59         187  
  59         2002  
26 59     59   29256 use Config::Model::Exception;
  59         270  
  59         3115  
27 59     59   40972 use Config::Model::Node;
  59         417  
  59         2776  
28 59     59   528 use Config::Model::Loader;
  59         142  
  59         1516  
29 59     59   30839 use Config::Model::SearchElement;
  59         236  
  59         2509  
30 59     59   29103 use Config::Model::Iterator;
  59         183  
  59         2023  
31 59     59   467 use Config::Model::ObjTreeScanner;
  59         147  
  59         1164  
32              
33 59     59   311 use warnings ;
  59         172  
  59         2034  
34              
35 59     59   362 use Carp qw/carp croak confess cluck/;
  59         167  
  59         230784  
36              
37             my $logger = get_logger("Instance");
38             my $change_logger = get_logger("Anything::Change");
39             my $user_logger = get_logger("User");
40              
41             has [qw/root_class_name/] => ( is => 'ro', isa => 'Str', required => 1 );
42              
43 139     139 0 1074 sub location { return "in instance" }
44              
45             has config_model => (
46             is => 'ro',
47             isa => 'Config::Model',
48             weak_ref => 1,
49             required => 1
50             );
51              
52             has check => (
53             is => 'ro',
54             isa => 'Str',
55             default => 'yes',
56             reader => 'read_check',
57             );
58              
59             # used by cme -create option
60             has auto_create => (
61             is => 'ro',
62             isa => 'Bool',
63             default => 0,
64             );
65              
66             # a unique (instance wise) placeholder for various tree objects
67             # to store information
68             has _safe => (
69             is => 'rw',
70             isa => 'HashRef',
71             traits => ['Hash'],
72             default => sub { {} },
73             handles => {
74             data => 'accessor',
75             },
76             );
77              
78             has appli_info => (
79             is => 'rw',
80             isa => 'HashRef',
81             traits => ['Hash'],
82             default => sub { {} },
83             handles => {
84             get_appli_info => 'get',
85             # currying See Moose::Manual::Delegation
86             get_support_info => [qw/get support_info/],
87             },
88             );
89              
90              
91             # preset mode: to load values found by HW scan or other automatic scheme
92             # layered mode: to load values found in included files (e.g. a la multistrap)
93             # canonical mode: write config data back using model order instead of user order
94             has [qw/preset layered canonical/] => (
95             is => 'ro',
96             isa => 'Bool',
97             default => 0,
98             );
99              
100             has changes => (
101             is => 'ro',
102             isa => 'ArrayRef',
103             traits => ['Array'],
104             default => sub { [] },
105             handles => {
106             add_change => 'push',
107             c_count => 'count',
108             has_changes => 'count',
109              
110             #needs_save => 'count' ,
111             clear_changes => 'clear',
112             } );
113              
114             sub needs_save {
115 65     65 1 13793 my $self = shift;
116 65         123 my $arg = shift;
117 65 50       191 if ( defined $arg ) {
118 0 0       0 if ($arg) {
119 0         0 croak "replace needs_save(1) call with add_change";
120 0         0 $self->add_change(); # may not work
121             }
122             else {
123 0         0 croak "replace needs_save(0) call with clear_changes";
124 0         0 $self->clear_changes;
125             }
126             }
127 65         253 return $self->c_count;
128             }
129              
130             has errors => (
131             is => 'ro',
132             isa => 'HashRef',
133             traits => ['Hash'],
134             default => sub { {} },
135             handles => {
136             _set_error => 'set',
137             cancel_error => 'delete',
138             has_error => 'count',
139             clear_errors => 'clear',
140             error_paths => 'keys'
141             } );
142              
143             sub add_error {
144 21     21 0 52 my $self = shift;
145 21         84 $self->_set_error( shift, '' );
146             }
147              
148             sub error_messages {
149 9     9 1 7271 my $self = shift;
150 9         40 my @errs = map { "$_: " . $self->config_root->grab($_)->error_msg } $self->error_paths;
  13         160  
151 9 50       67 return wantarray ? @errs : join( "\n", @errs );
152             }
153              
154             sub has_warning {
155 3     3 1 551 my $self = shift;
156              
157             my $count_leaf_warnings = sub {
158 75     75   465 my ( $scanner, $data_ref, $node, $element_name, $index, $leaf_object ) = @_;
159 75         202 $$data_ref += $leaf_object->has_warning;
160 3         18 };
161              
162             my $count_list_warnings = sub {
163 9     9   20 my ( $scanner, $data_ref, $node, $element_name, $index, $leaf_object ) = @_;
164 9         27 $$data_ref += $node->fetch_element($element_name)->has_warning;
165 3         13 };
166              
167 3         28 my $scan = Config::Model::ObjTreeScanner->new(
168             leaf_cb => $count_leaf_warnings,
169             list_element_hook => $count_list_warnings,
170             hash_element_hook => $count_list_warnings,
171             );
172              
173 3         11 my $result = 0;
174 3         21 $scan->scan_node( \$result, $self->config_root );
175              
176 3         73 return $result;
177             }
178              
179             has on_change_cb => (
180             is => 'rw',
181             traits => ['Code'],
182             isa => 'CodeRef',
183             default => sub { sub { } },
184             );
185              
186             has on_message_cb => (
187             traits => ['Code'],
188             is => 'rw',
189             isa => 'CodeRef',
190             default => sub { sub { say @_; } },
191             handles => {
192             show_message => 'execute',
193             },
194             );
195              
196             # initial_load mode: when data is loaded the first time
197             has initial_load => (
198             is => 'rw',
199             isa => 'Bool',
200             default => 0,
201             trigger => \&_trace_initial_load,
202             traits => [qw/Bool/],
203             handles => {
204             initial_load_start => 'set',
205             initial_load_stop => 'unset',
206             } );
207              
208             sub _trace_initial_load {
209 206     206   8420 my ( $self, $n, $o ) = @_;
210 206         878 $logger->debug("switched to $n");
211             }
212              
213             # This array holds a set of sub ref that will be invoked when
214             # the user requires to write all configuration tree in their
215             # backend storage.
216             has _write_back => (
217             is => 'ro',
218             isa => 'HashRef',
219             traits => ['Hash'],
220             handles => {
221             count_write_back => 'count', # mostly for tests
222             has_no_write_back => 'is_empty',
223             nodes_to_write_back => 'keys',
224             write_back_node_info => 'get',
225             delete_write_back => 'delete',
226             clear_write_back => 'clear',
227             },
228             default => sub { {} },
229             );
230              
231             sub register_write_back {
232 93     93 1 326 my ($self, $path, $backend, $wb) = @_;
233 93   100     172 push @{ $self->_write_back->{$path} //= [] }, [$backend, $wb];
  93         1001  
234             }
235              
236             # used for auto_read auto_write feature
237             has [qw/name application backend_arg backup/] => (
238             is => 'ro',
239             isa => 'Maybe[Str]',
240             );
241              
242             has 'root_dir' => (
243             is => 'ro',
244             isa => 'Config::Model::TypeContraints::Path',
245             coerce => 1
246             );
247              
248             has root_path => (
249             is => 'ro',
250             isa => 'Path::Tiny',
251             lazy_build => 1,
252             );
253              
254             sub _build_root_path {
255 2     2   57 my $self = shift;
256 2   100     54 my $root_dir = $self->root_dir // '';
257 2 100       21 return $root_dir ? path($root_dir) : Path::Tiny->cwd;
258             }
259              
260             has [qw/config_dir config_file/] => (
261             is => 'ro',
262             isa => 'Config::Model::TypeContraints::Path',
263             coerce => 1
264             );
265              
266             has tree => (
267             is => 'ro',
268             isa => 'Config::Model::Node',
269             builder => '_build_tree',
270             lazy => 1,
271             clearer => '_clear_config',
272             reader => 'config_root',
273             handles => [qw/apply_fixes deep_check grab grab_value/],
274             );
275              
276             sub reset_config {
277 1     1 1 477 my $self = shift;
278 1         6 $self->_clear_config;
279 1         5 $self->clear_changes;
280 1         23 return $self->config_root;
281             }
282              
283             sub _build_tree {
284 139     139   39231 my $self = shift;
285              
286             return $self->load_node (
287             config_class_name => $self->{root_class_name},
288             instance => $self,
289             container => $self,
290             config_file => $self->{config_file},
291 139         1158 );
292             }
293              
294             sub preset_start {
295 5     5 1 3915 my $self = shift;
296 5         33 $logger->info("Starting preset mode");
297             carp "Cannot start preset mode during layered mode"
298 5 50       77 if $self->{layered};
299 5         21 $self->{preset} = 1;
300             }
301              
302             sub preset_stop {
303 5     5 1 35 my $self = shift;
304 5         24 $logger->info("Stopping preset mode");
305 5         50 $self->{preset} = 0;
306             }
307              
308             sub preset_clear {
309 1     1 1 4 my $self = shift;
310              
311             my $leaf_cb = sub {
312 42     42   84 my ( $scanner, $data_ref, $node, $element_name, $index, $leaf_object ) = @_;
313 42   100     164 $$data_ref ||= $leaf_object->clear_preset;
314 1         7 };
315              
316 1         6 $self->_stuff_clear($leaf_cb);
317             }
318              
319             sub layered_start {
320 15     15 1 678 my $self = shift;
321 15         87 $logger->info("Starting layered mode");
322             carp "Cannot start layered mode during preset mode"
323 15 50       219 if $self->{preset};
324 15         67 $self->{layered} = 1;
325             }
326              
327             sub layered_stop {
328 14     14 1 103 my $self = shift;
329 14         65 $logger->info("Stopping layered mode");
330 14         153 $self->{layered} = 0;
331             }
332              
333             sub layered_clear {
334 10     10 1 28 my $self = shift;
335              
336             my $leaf_cb = sub {
337 137     137   298 my ( $scanner, $data_ref, $node, $element_name, $index, $leaf_object ) = @_;
338 137   100     2458 $$data_ref ||= $leaf_object->clear_layered;
339 10         55 };
340              
341 10         51 $self->_stuff_clear($leaf_cb);
342             }
343              
344             sub get_data_mode {
345 1665     1665 1 3283 my $self = shift;
346             return
347             $self->{layered} ? 'layered'
348 1665 100       6062 : $self->{preset} ? 'preset'
    100          
349             : 'normal';
350             }
351              
352             sub _stuff_clear {
353 11     11   27 my ( $self, $leaf_cb ) = @_;
354              
355             # this sub may remove hash keys that were entered by user if the
356             # corresponding hash value has no data.
357             # it also clear auto_created ids if there's no data in there
358             my $h_cb = sub {
359 48     48   125 my ( $scanner, $data_ref, $node, $element_name, @keys ) = @_;
360 48         131 my $obj = $node->fetch_element($element_name);
361              
362             # Since remove method uses splice(array) on list elements, the
363             # removal must be done in reverse order to avoid messing up
364             # the indexes of the array (i.e. the last indexes becomes
365             # greater than the length of the array).
366 48         208 foreach my $k (reverse @keys) {
367 65         105 my $has_data = 0;
368 65         205 $scanner->scan_hash( \$has_data, $node, $element_name, $k );
369 65 100       166 $obj->remove($k) unless $has_data;
370 65   100     420 $$data_ref ||= $has_data;
371             }
372 11         49 };
373              
374 11         94 my $wiper = Config::Model::ObjTreeScanner->new(
375             fallback => 'all',
376             auto_vivify => 0,
377             check => 'skip',
378             leaf_cb => $leaf_cb,
379             hash_element_cb => $h_cb,
380             list_element_cb => $h_cb,
381             );
382              
383 11         81 $wiper->scan_node( undef, $self->config_root );
384              
385             }
386              
387             sub modify {
388 2     2 1 52 my $self = shift ;
389 2 50       15 my %args = @_ eq 1 ? ( step => $_[0] ) : @_;
390 2   33     13 my $force = delete $args{force_save} || delete $args{force};
391 2         5 my $quiet = delete $args{quiet};
392 2         13 $self->load(%args);
393 2 50       28 $self->say_changes() unless $quiet;
394 2         9 $self->write_back( force => $force );
395 2         39 return $self;
396             }
397              
398             sub load {
399 3     3 1 1845 my $self = shift;
400 3         56 my $loader = Config::Model::Loader->new( start_node => $self->config_root );
401 3 50       160 my %args = @_ eq 1 ? ( step => $_[0] ) : @_;
402 3         28 $loader->load( %args );
403 3         33 return $self;
404             }
405              
406             sub search_element {
407 0     0 0 0 my $self = shift;
408 0         0 $self->config_root->search_element(@_);
409             }
410              
411             sub wizard_helper {
412 0     0 1 0 carp __PACKAGE__, "::wizard_helper helped is deprecated. Call iterator instead";
413 0         0 goto &iterator;
414             }
415              
416             sub iterator {
417 1     1 1 2 my $self = shift;
418 1         5 my @args = @_;
419              
420 1         5 my $tree_root = $self->config_root;
421              
422 1         11 return Config::Model::Iterator->new( root => $tree_root, @args );
423             }
424              
425             sub read_directory {
426 0     0 0 0 carp "read_directory is deprecated";
427 0         0 return shift->root_dir;
428             }
429              
430             sub write_directory {
431 0     0 0 0 my $self = shift;
432 0         0 carp "write_directory is deprecated";
433 0         0 return $self->root_dir;
434             }
435              
436             sub write_root_dir {
437 0     0 0 0 my $self = shift;
438 0         0 carp "deprecated";
439 0         0 return $self->root_dir;
440             }
441              
442             # FIXME: record changes to implement undo/redo ?
443             sub notify_change {
444 1520     1520 1 2531 my $self = shift;
445 1520         6890 my %args = @_;
446 1520 100       3996 if ( $change_logger->is_debug ) {
447 95         618 $change_logger->debug( "in instance ", $self->name, ' for path ', $args{path} );
448             }
449              
450 1520         10514 foreach my $obsolete (qw/note_only msg/) {
451 3040 50       8001 if ( my $m = delete $args{$obsolete} ) {
452 0         0 carp "notify_change: param $obsolete is obsolete ($m)";
453 0   0     0 $args{note} //='';
454 0         0 $args{note} .= $m;
455             }
456             }
457              
458 1520         6126 $self->add_change( \%args );
459 1520         29460 $self->on_change_cb->( %args );
460             }
461              
462             sub _truncate {
463 37     37   91 my @lines = @_;
464 37         79 foreach my $l (@lines) {
465 74 100       140 next unless defined $l;
466 52         103 $l =~ s/\n/ /g;
467 52 50       113 substr ($l, 60) = '[...]' if length $l > 60; # limit string length
468             }
469 37         117 return @lines;
470             }
471              
472             sub list_changes {
473 19     19 1 5454 my $self = shift;
474 19         77 my $l = $self->changes;
475 19         46 my @all;
476              
477 19         58 foreach my $c (@$l) {
478 37         79 my $path = $c->{path} ;
479              
480 37   100     110 my $vt = $c->{value_type} || '';
481 37         116 my ( $o, $n ) = _truncate( $c->{old}, $c->{new} );
482              
483 37 100       131 my $note = $c->{note} ? " # $c->{note}" : '';
484              
485 37 100 100     322 if ( defined $n and not defined $o ) {
    100 100        
    100 66        
    50          
486 2         10 push @all, "$path has new value: '$n'$note";
487             }
488             elsif ( not defined $n and defined $o) {
489 6         22 push @all, "$path deleted value: '$o'$note";
490             }
491             elsif ( defined $o and defined $n ) {
492 22         109 push @all, "$path: '$o' -> '$n'$note";
493             }
494             elsif ( defined $c->{note} ) {
495 7         37 push @all, "$path: ".$c->{note};
496             }
497             else {
498             # something's unexpected with the call to notify_change
499 0         0 push @all, "changed ".join(' ', each %$c);
500             }
501             }
502              
503 19 100       221 return wantarray ? @all : join( "\n", @all );
504             }
505              
506             sub say_changes {
507 2     2 1 6 my $self = shift;
508 2         10 my @changes = $self->list_changes;
509 2 50       9 return $self unless @changes;
510              
511 2   33     23 my $msg = "\n" .
512             join( "\n- ", "Changes applied to " . ($self->application // $self->name) . " configuration:", @changes ) .
513             "\n";
514              
515 2         11 $user_logger->info($msg);
516 2         56 return $self;
517             }
518              
519             sub write_back {
520 39     39 1 13824 my $self = shift;
521 39 50       267 my %args =
    100          
522             scalar @_ > 1 ? @_
523             : scalar @_ == 1 ? ( config_dir => $_[0] )
524             : ();
525              
526 39   100     216 my $force_write = delete $args{force} || 0;
527              
528 39 50       162 if (delete $args{root}) {
529 0         0 say "write_back: root argument is no longer supported";
530             }
531              
532             # make sure that root node is loaded
533 39         348 $self->config_root->init;
534              
535 39 100       187 if ($force_write) {
536             # make sure that the whole tree is loaded
537 20         97 my $dump = $self->config_root->dump_tree;
538             }
539              
540 39         217 foreach my $k ( keys %args ) {
541 2 50       13 if ($k eq 'config_dir') {
    50          
542 0   0     0 $args{$k} ||= '';
543 0 0 0     0 $args{$k} .= '/' if $args{$k} and $args{$k} !~ m(/$);
544             }
545             elsif ( $k ne 'config_file' ) {
546 0         0 croak "write_back: wrong parameters $k";
547             }
548             }
549              
550 39 50       251 if ($self->has_no_write_back ) {
551 0 0       0 my $info = $self->application ? "the model of application ".$self->application
552             : "model ".$self->root_class_name ;
553 0         0 croak "Don't know how to save data of $self->{name} instance. ",
554             "Either $info has no configured ",
555             "read/write backend or no node containing a backend was loaded. ",
556             "Try with -force option or add read/write backend to $info\n";
557             }
558              
559 39         643 foreach my $path ( sort $self->nodes_to_write_back ) {
560 52         769 $logger->info("write_back called on node $path");
561              
562 52 50 66     583 if ( $path and $self->{config_file} ) {
563 0         0 $logger->warn("write_back: cannot override config_file in non root node ($path)");
564             delete $self->{config_file}
565 0         0 }
566              
567 52         234 $self->_write_back_node(%args, path => $path, force_write => $force_write) ;
568             }
569 39         508 $self->clear_changes;
570             }
571              
572             sub _write_back_node {
573 52     52   139 my $self = shift;
574 52         218 my %args = @_;
575              
576 52         161 my $path = delete $args{path};
577 52         117 my $force_write = delete $args{force_write};
578              
579 52         360 my $node = $self->config_root->grab(
580             step => $path,
581             type => 'node',
582             mode => 'loose',
583             autoadd => 0,
584             );
585              
586 52         149 foreach my $wb_info (@{ $self->write_back_node_info($path) }) {
  52         346  
587 52         997 my ($backend, $cb) = @$wb_info;
588              
589             my @wb_args = (
590             %args,
591             config_file => $self->{config_file},
592 52         391 force => $force_write,
593             backup => $self->backup,
594             );
595              
596 52 50 66     531 if (defined $node and ($node->needs_save or $force_write)) {
      100        
597 51         131 my $dir = $args{config_dir};
598 51 50 33     203 mkpath( $dir, 0, oct(755) ) if $dir and not -d $dir;
599              
600             # exit when write is successfull
601 51         217 my $res = $cb->(@wb_args);
602 51 50       569 $logger->info( "write_back called with $backend backend, result is ",
603             defined $res ? $res : '<undef>' );
604             }
605              
606 52 100       826 if (not defined $node) {
607 1         14 $logger->debug("deleting file for deleted node $path");
608 1         15 $cb->(@wb_args, force_delete => 1);
609 1         7 $self->delete_write_back($path);
610             }
611             }
612              
613 52         354 $logger->trace( "write_back on node '$path' done" );
614             }
615              
616             sub save {
617 2     2 1 392 goto &write_back;
618             }
619              
620             sub update {
621 0     0 1 0 my ($self, %args) = @_;
622              
623 0         0 my @msgs ;
624             my $hook = sub {
625 0     0   0 my ($scanner, $data_ref,$node,@element_list) = @_;
626 0 0       0 if ($node->can('update')) {
627 0         0 my $loc = $node->location;
628 0 0 0     0 say "Calling update on node '$loc'" if $loc and not $args{quiet};
629 0         0 push (@msgs, $node->update(%args))
630             } ;
631 0         0 };
632              
633 0         0 my $root = $self->config_root ;
634              
635             Config::Model::ObjTreeScanner->new(
636             node_content_hook => $hook,
637             check => ($args{quiet} ? 'no' : 'yes'),
638       0     leaf_cb => sub { }
639 0 0       0 )->scan_node( \@msgs, $root );
640              
641 0         0 return @msgs;
642             }
643              
644             sub DEMOLISH {
645 121     121 1 3356003 my $self = shift;
646 121         651 $self->clear_write_back; # avoid reference loops
647             }
648              
649             __PACKAGE__->meta->make_immutable;
650              
651             1;
652              
653             # ABSTRACT: Instance of configuration tree
654              
655             __END__
656              
657             =pod
658              
659             =encoding UTF-8
660              
661             =head1 NAME
662              
663             Config::Model::Instance - Instance of configuration tree
664              
665             =head1 VERSION
666              
667             version 2.153
668              
669             =head1 SYNOPSIS
670              
671             use Config::Model;
672             use File::Path ;
673              
674             # setup a dummy popcon conf file
675             my $wr_dir = '/tmp/etc/';
676             my $conf_file = "$wr_dir/popularity-contest.conf" ;
677              
678             unless (-d $wr_dir) {
679             mkpath($wr_dir, { mode => 0755 })
680             || die "can't mkpath $wr_dir: $!";
681             }
682             open(my $conf,"> $conf_file" ) || die "can't open $conf_file: $!";
683             $conf->print( qq!MY_HOSTID="aaaaaaaaaaaaaaaaaaaa"\n!,
684             qq!PARTICIPATE="yes"\n!,
685             qq!USEHTTP="yes" # always http\n!,
686             qq!DAY="6"\n!);
687             $conf->close ;
688              
689             my $model = Config::Model->new;
690              
691             # PopCon model is provided. Create a new Config::Model::Instance object
692             my $inst = $model->instance (root_class_name => 'PopCon',
693             root_dir => '/tmp',
694             );
695             my $root = $inst -> config_root ;
696              
697             print $root->describe;
698              
699             =head1 DESCRIPTION
700              
701             This module provides an object that holds a configuration tree.
702              
703             =head1 CONSTRUCTOR
704              
705             An instance object is created by calling L<instance
706             method|Config::Model/"Configuration instance"> on an existing
707             model. This model can be specified by its application name:
708              
709             my $inst = $model->instance (
710             # run 'cme list' to get list of applications
711             application => 'foo',
712             # optional
713             instance_name => 'test1'
714             );
715              
716             my $inst = $model->instance (
717             root_class_name => 'SomeRootClass',
718             instance_name => 'test1'
719             );
720              
721             The directory (or directories) holding configuration files is
722             specified within the configuration model. For test purpose you can
723             change the "root" directory with C<root_dir> parameter.
724              
725             Constructor parameters are:
726              
727             =over
728              
729             =item root_dir
730              
731             Pseudo root directory where to read I<and> write configuration
732             files (L<Path::Tiny> object or string). Configuration directory
733             specified in model or with C<config_dir> option is appended to this
734             root directory
735              
736             =item root_path
737              
738             L<Path::Tiny> object created with C<root_dir> value or with current
739             directory if C<root_dir> is empty.
740              
741             =item config_dir
742              
743             Directory to read or write configuration file. This parameter must be
744             supplied if not provided by the configuration model. (string)
745              
746             =item backend_arg
747              
748             Specify a backend argument that may be retrieved by some
749             backend. Instance is used as a relay and does not use this data.
750              
751             =item check
752              
753             Specify whether to check value while reading config files. Either:
754              
755             =over
756              
757             =item yes
758              
759             Check value and throws an error for bad values.
760              
761             =item skip
762              
763             Check value and skip bad value.
764              
765             =item no
766              
767             Do not check.
768              
769             =back
770              
771             =item canonical
772              
773             When true: write config data back using model order. By default, write
774             items back using the order found in the configuration file. This
775             feature is experimental and not supported by all backends.
776              
777             =item on_change_cb
778              
779             Call back this function whenever C<notify_change> is called. Called with
780             arguments: C<< name => <root node element name>, index => <index_value> >>
781              
782             =item on_message_cb
783              
784             Call back this function when L<show_message> is called. By default,
785             messages are displayed on STDOUT.
786              
787             =item error_paths
788              
789             Returns a list of tree items that currently have an error.
790              
791             =item error_messages
792              
793             Returns a list of error messages from the tree content.
794              
795             =back
796              
797             Note that the root directory specified within the configuration model
798             is overridden by C<root_dir> parameter.
799              
800             If you need to load configuration data that are not correct, you can
801             use C<< force_load => 1 >>. Then, wrong data are discarded (equivalent to
802             C<< check => 'no' >> ).
803              
804             =head1 METHODS
805              
806             =head2 Manage configuration data
807              
808             =head2 modify
809              
810             Calls L</"load"> and then L</save>.
811              
812             Takes the same parameter as C<load> plus:
813              
814             =over
815              
816             =item C<force_write>
817              
818             Force saving configuration file even if no value was modified
819             (default is 0)
820              
821             =item C<quiet>
822              
823             Do no display the changes brought by the modification steps
824              
825             =back
826              
827             =head2 load
828              
829             Load configuration tree with configuration data. See
830             L<Config::Model::Loader/"load"> for parameters.
831             Returns <$self>.
832              
833             =head2 save
834              
835             Save the content of the configuration tree to
836             configuration files. (See L</write_back> for more details)
837              
838             Use C<< force => 1 >> option to force saving configuration data.
839              
840             =head2 config_root
841              
842             Returns the L<root object|Config::Model::Node> of the configuration tree.
843              
844             =head2 apply_fixes
845              
846             Scan the tree and apply fixes that are attached to warning specifications.
847             See C<warn_if_match> or C<warn_unless_match> in L<Config::Model::Value/>.
848              
849             =head2 deep_check
850              
851             Scan the tree and deep check on all elements that support this. Currently only hash or
852             list element have this feature.
853              
854             =head2 needs_save
855              
856             Returns 1 (or more) if the instance contains data that needs to be
857             saved. I.e some change were done in the tree that needs to be saved.
858              
859             =head2 has_changes
860              
861             Returns true if the instance contains unsasved changes.
862              
863             =head2 list_changes
864              
865             In list context, returns a array ref of strings describing the changes.
866             In scalar context, returns a big string. Useful to print.
867              
868             =head2 say_changes
869              
870             Print all changes on STDOUT and return C<$self>.
871              
872             =head2 clear_changes
873              
874             Clear list of changes. Note that changes pending in the configuration
875             tree is not affected. This clears only the list shown to user. Use
876             only for tests.
877              
878             =head2 has_warning
879              
880             Returns the number of warning found in the elements of this configuration instance.
881              
882             =head2 update
883              
884             Parameters: C<< ( quiet => (0|1), %args ) >>
885              
886             Try to run update command on all nodes of the configuration tree. Node
887             without C<update> method are ignored. C<update> prints a message
888             otherwise (unless C<quiet> is true).
889              
890             =head2 grab
891              
892             Use the steps parameter to retrieve and returns an object from the
893             configuration tree. Forwarded to L<Config::Model::Role::Grab/grab>
894              
895             =head2 grab_value
896              
897             Use the steps parameter to retrieve and returns the value of a leaf
898             object from the configuration tree. Forwarded to
899             L<Config::Model::Role::Grab/grab_value>
900              
901             =head2 searcher
902              
903             Returns an object dedicated to search an element in the configuration
904             model.
905              
906             This method returns a L<Config::Model::Searcher> object. See
907             L<Config::Model::Searcher> for details on how to handle a search.
908              
909             =head2 iterator
910              
911             This method returns a L<Config::Model::Iterator> object. See
912             L<Config::Model::Iterator> for details.
913              
914             Arguments are explained in L<Config::Model::Iterator>
915             L<constructor arguments|Config::Model::Iterator/"Creating an iterator">.
916              
917             =head2 application
918              
919             Returns the application name of the instance. (E.g C<popcon>, C<dpkg> ...)
920              
921             =head2 wizard_helper
922              
923             Deprecated. Call L</iterator> instead.
924              
925             =head1 Internal methods
926              
927             =head2 name
928              
929             Returns the instance name.
930              
931             =head2 read_check
932              
933             Returns which kind of check is performed while reading configuration
934             files. (see C<check> parameter in L</CONSTRUCTOR> section)
935              
936             =head2 show_message
937              
938             Parameters: C<( string )>
939              
940             Display the message on STDOUT unless a custom function was passed to
941             C<on_message_cb> parameter.
942              
943             =head2 reset_config
944              
945             Destroy current configuration tree (with data) and returns a new tree with
946             data (and annotations) loaded from disk.
947              
948             =head2 config_model
949              
950             Returns the model (L<Config::Model> object) of the configuration tree.
951              
952             =head2 annotation_saver
953              
954             Returns the object loading and saving annotations. See
955             L<Config::Model::Annotation> for details.
956              
957             =head2 preset_start
958              
959             All values stored in preset mode are shown to the user as default
960             values. This feature is useful to enter configuration data entered by
961             an automatic process (like hardware scan)
962              
963             =head2 preset_stop
964              
965             Stop preset mode
966              
967             =head2 preset
968              
969             Get preset mode
970              
971             =head2 preset_clear
972              
973             Clear all preset values stored.
974              
975             =head2 layered_start
976              
977             All values stored in layered mode are shown to the user as default
978             values. This feature is useful to enter configuration data entered by
979             an automatic process (like hardware scan)
980              
981             =head2 layered_stop
982              
983             Stop layered mode
984              
985             =head2 layered
986              
987             Get layered mode
988              
989             =head2 layered_clear
990              
991             Clear all layered values stored.
992              
993             =head2 get_data_mode
994              
995             Returns 'normal' or 'preset' or 'layered'. Does not take into account
996             initial_load.
997              
998             =head2 initial_load_start
999              
1000             Start initial_load mode. This mode tracks the first modifications of
1001             the tree done with data read from the configuration file.
1002              
1003             Instance is built with initial_load as 1. Read backend clears this
1004             value once the first read is done.
1005              
1006             Other modifications, when initial_load is zero, are assumed to be user
1007             modifications.
1008              
1009             =head2 initial_load_stop
1010              
1011             Stop initial_load mode. Instance is built with initial_load as 1. Read backend
1012             clears this value once the first read is done.
1013              
1014             =head2 initial_load
1015              
1016             Get initial_load mode
1017              
1018             =head2 data
1019              
1020             This method provides a way to store some arbitrary data in the
1021             instance object.
1022              
1023             E.g:
1024              
1025             $instance->data(foo => 'bar');
1026              
1027             Later:
1028              
1029             my $foo = $instance->data('foo'); # $foo contains 'bar'
1030              
1031             =head1 Read and write backend features
1032              
1033             Usually, a program based on config model must first create the
1034             configuration model, then load all configuration data.
1035              
1036             This feature enables you to declare with the model a way to load
1037             configuration data (and to write it back). See
1038             L<Config::Model::BackendMgr> for details.
1039              
1040             =head2 backend_arg
1041              
1042             Get L<cme> command line argument that may be used by the backend to
1043             get the configuration file. These method is typically used in the read
1044             and write method of a backend to know where is the configuration file
1045             to edit.
1046              
1047             =head2 root_dir
1048              
1049             Returns a L<Path::Tiny> object for the root directory where
1050             configuration data is read from or written to.
1051              
1052             =head2 root_path
1053              
1054             Same as C<root_dir>
1055              
1056             =head2 register_write_back
1057              
1058             Parameters: C<( node_location )>
1059              
1060             Register a node path that is called back with
1061             C<write_back> method.
1062              
1063             =head2 notify_change
1064              
1065             Notify that some data has changed in the tree. See
1066             L<Config::Model::AnyThing/notify_change> for more details.
1067              
1068             =head2 write_back
1069              
1070             In summary, save the content of the configuration tree to
1071             configuration files.
1072              
1073             In more details, C<write_back> tries to run all subroutines registered
1074             with C<register_write_back> to write the configuration information.
1075             (See L<Config::Model::BackendMgr> for details).
1076              
1077             You can specify here another config directory to write configuration
1078             data back with C<config_dir> parameter. This overrides the model
1079             specifications.
1080              
1081             C<write_back> croaks if no write call-back are known.
1082              
1083             Use C<< force => 1 >> option to force saving configuration data. This
1084             is useful to write back a file even no change are done at semantic
1085             level, i.e. to reformat a file or remove unnecessary data.
1086              
1087             =head1 AUTHOR
1088              
1089             Dominique Dumont, (ddumont at cpan dot org)
1090              
1091             =head1 SEE ALSO
1092              
1093             L<Config::Model>,
1094             L<Config::Model::Node>,
1095             L<Config::Model::Loader>,
1096             L<Config::Model::Searcher>,
1097             L<Config::Model::Value>,
1098              
1099             =head1 AUTHOR
1100              
1101             Dominique Dumont
1102              
1103             =head1 COPYRIGHT AND LICENSE
1104              
1105             This software is Copyright (c) 2005-2022 by Dominique Dumont.
1106              
1107             This is free software, licensed under:
1108              
1109             The GNU Lesser General Public License, Version 2.1, February 1999
1110              
1111             =cut