Config-Model
view release on metacpan or search on metacpan
lib/Config/Model/CheckList.pm view on Meta::CPAN
#
# This file is part of Config-Model
#
# This software is Copyright (c) 2005-2022 by Dominique Dumont.
#
# This is free software, licensed under:
#
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::CheckList 2.162;
use Mouse;
use 5.020;
use feature qw/postderef signatures/;
no warnings qw/experimental::postderef experimental::signatures/;
use Config::Model::Exception;
use Config::Model::IdElementReference;
use Config::Model::Warper;
use List::MoreUtils qw/any none/;
use Carp;
use Log::Log4perl qw(get_logger :levels);
use Storable qw/dclone/;
extends qw/Config::Model::AnyThing/;
with "Config::Model::Role::WarpMaster";
with "Config::Model::Role::Grab";
with "Config::Model::Role::HelpAsText";
with "Config::Model::Role::ComputeFunction";
with "Config::Model::Role::Utils";
my $logger = get_logger("Tree.Element.CheckList");
my $user_logger = get_logger("User");
my @introspect_params = qw/refer_to computed_refer_to/;
my @accessible_params = qw/default_list upstream_default_list choice ordered/;
my @allowed_warp_params = ( @accessible_params, qw/level/ );
has [qw/backup data preset layered/] => ( is => 'rw', isa => 'HashRef', default => sub { {}; } );
has computed_refer_to => ( is => 'rw', isa => 'Maybe[HashRef]' );
has [qw/refer_to/] => ( is => 'rw', isa => 'Str' );
has [qw/ordered_data choice/] => ( is => 'rw', isa => 'ArrayRef', default => sub { []; } );
has [qw/ordered/] => ( is => 'ro', isa => 'Bool' );
has [qw/warp help/] => ( is => 'rw', isa => 'Maybe[HashRef]' );
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
my %args = @_;
my %h = map { ( $_ => $args{$_} ); } grep { defined $args{$_} } @allowed_warp_params;
return $class->$orig( backup => dclone( \%h ), @_ );
};
sub BUILD {
my $self = shift;
if ( defined $self->refer_to or defined $self->computed_refer_to ) {
$self->submit_to_refer_to();
}
$self->set_properties(); # set will use backup data
if ( defined $self->warp ) {
my $warp_info = $self->warp;
$self->{warper} = Config::Model::Warper->new(
warped_object => $self,
%$warp_info,
allowed => \@allowed_warp_params
);
}
$self->cl_init;
$logger->info( "Created check_list element " . $self->element_name );
return $self;
}
sub cl_init {
my $self = shift;
$self->warp if ( $self->{warp} );
if ( defined $self->{ref_object} ) {
my $level = $self->parent->get_element_property(
element => $self->{element_name},
property => 'level',
);
$self->{ref_object}->get_choice_from_referred_to if $level ne 'hidden';
}
return;
}
sub name {
my $self = shift;
my $name = $self->{parent}->name . ' ' . $self->{element_name};
return $name;
}
sub value_type { return 'check_list'; }
# warning : call to 'set' are not cumulative. Default value are always
# restored. Lest keeping track of what was modified with 'set' is
# too hard for the user.
sub set_properties ($self, @args) {
# cleanup all parameters that are handled by warp
for (@allowed_warp_params) {
delete $self->{$_};
}
if ( $logger->is_trace() ) {
my %h = @args;
my $keys = join( ',', keys %h );
$logger->trace("set_properties called on $self->{element_name} with $keys");
}
# merge data passed to the constructor with data passed to set
my %args = ( %{ $self->{backup} }, @args );
# these are handled by Node or Warper
for (qw/level/) {
delete $args{$_}
}
$self->{ordered} = delete $args{ordered} || 0;
if ( defined $args{choice} ) {
my @choice = @{ delete $args{choice} };
$self->{default_choice} = \@choice;
$self->setup_choice(@choice);
}
if ( defined $args{default} ) {
$logger->warn($self->name, ": default param is deprecated, use default_list");
$args{default_list} = delete $args{default};
}
if ( defined $args{default_list} ) {
$self->{default_list} = delete $args{default_list};
}
# store default data in a hash (more convenient)
$self->{default_data} = { map { $_ => 1 } @{ $self->{default_list} } };
if ( defined $args{upstream_default_list} ) {
$self->{upstream_default_list} = delete $args{upstream_default_list};
}
# store upstream default data in a hash (more convenient)
$self->{upstream_default_data} =
{ map { $_ => 1 } @{ $self->{upstream_default_list} } };
Config::Model::Exception::Model->throw(
object => $self,
error => "Unexpected parameters :" . join( ' ', keys %args ) ) if scalar keys %args;
if ( $self->has_warped_slaves ) {
my $hash = $self->get_checked_list_as_hash; # force scalar context
$self->trigger_warp($hash, $self->fetch);
}
return;
}
sub setup_choice ($self, @args) {
my @choice = ref $args[0] ? @{ $args[0] } : @args;
$logger->trace("CheckList $self->{element_name}: setup_choice with @choice");
# store all enum values in a hash. This way, checking
# whether a value is present in the enum set is easier
delete $self->{choice_hash} if defined $self->{choice_hash};
for (@choice) {
$self->{choice_hash}{$_} = 1;
}
$self->{choice} = \@choice;
# cleanup current preset and data if it does not fit current choices
lib/Config/Model/CheckList.pm view on Meta::CPAN
return;
}
sub get_info {
my $self = shift;
my @items = ('type: check_list');
if ( defined $self->refer_to ) {
push @items, "refer_to: " . $self->refer_to;
}
push @items, "ordered: " . ( $self->ordered ? 'yes' : 'no' );
return @items;
}
sub clear {
my $self = shift;
# also triggers notify changes
for my $item ($self->get_choice) {
$self->clear_item($item);
}
return;
}
sub clear_values { goto &clear; }
sub clear_layered {
my $self = shift;
$self->{layered} = {};
return;
}
my %old_mode = ( built_in_list => 'upstream_default_list', );
sub get_checked_list_as_hash ($self, @args) {
my %args = _resolve_arg_shortcut(\@args, 'mode');
my $mode = $args{mode} || '';
foreach my $k ( keys %old_mode ) {
next unless $mode eq $k;
$mode = $old_mode{$k};
carp $self->location, " warning: deprecated mode parameter: $k, ", "expected $mode\n";
}
if ( my $err = $self->is_bad_mode($mode)) {
croak "get_checked_list_as_hash: $err";
}
my $dat = $self->{data};
my $pre = $self->{preset};
my $def = $self->{default_data};
my $lay = $self->{layered};
my $ud = $self->{upstream_default_data};
# fill empty hash result
my %h = map { $_ => 0 } $self->get_choice;
my %predef = ( %$def, %$pre );
my %std = ( %$ud, %$lay, %$def, %$pre );
# use _std_backup if all data values are null (no checked items by user)
my %old_dat = ( none { $_; } values %$dat ) ? %{ $self->{_std_backup} || {} } : %$dat;
if ( not $mode and any { $_; } values %predef and none { $_; } values %old_dat ) {
# changed from nothing to default checked list that must be written
$self->{_std_backup} = { %$def, %$pre };
$self->notify_change( note => "use default checklist" );
}
# custom test must compare the whole list at once, not just one item at a time.
my %result =
$mode eq 'custom' ? ( ( grep { $dat->{$_} xor $std{$_} } keys %h ) ? ( %$pre, %$dat ) : () )
: $mode eq 'preset' ? (%$pre)
: $mode eq 'layered' ? (%$lay)
: $mode eq 'upstream_default' ? (%$ud)
: $mode eq 'default' ? (%$def)
: $mode eq 'standard' ? %std
: $mode eq 'user' ? ( %h, %std, %$dat )
: ( %predef, %$dat );
return wantarray ? %result : \%result;
}
sub get_checked_list ($self, @args) {
my %h = $self->get_checked_list_as_hash(@args);
my @good_order = $self->{ordered} ? @{ $self->{ordered_data} } : sort keys %h;
my @res = grep { $h{$_} } @good_order;
return wantarray ? @res : \@res;
}
sub fetch ($self, @args) {
return join( ',', $self->get_checked_list(@args) );
}
sub fetch_custom {
my $self = shift;
return join( ',', $self->get_checked_list('custom') );
}
sub fetch_preset {
my $self = shift;
return join( ',', $self->get_checked_list('preset') );
}
sub fetch_layered {
my $self = shift;
return join( ',', $self->get_checked_list('layered') );
}
sub get ($self, $path, @args){
if ($path) {
Config::Model::Exception::User->throw(
object => $self,
message => "get() called with a value with non-empty path: '$path'"
);
}
return $self->fetch(@args);
}
sub set {
my ($self, $path, $list, %args) = @_;
my $check_validity = $self->_check_check( $args{check} );
if ($path) {
Config::Model::Exception::User->throw(
object => $self,
( run in 2.648 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )