view Lib/IMPL/Resources/StringMap.pm @ 377:a0d342ac9a36

sync
author cin
date Tue, 14 Jan 2014 20:06:36 +0400
parents a54a2faf2f7e
children 2eed076cb944
line wrap: on
line source

package IMPL::Web::Resources::StringMap;
use strict;

use IMPL::Const qw(:prop);
use IMPL::declare {
	require => {
		Exception => 'IMPL::Exception',
		IOException => '-IMPL::IOException',
		ArgException => '-IMPL::InvalidArgumentException'
	},
	props => [
		_data => PROP_RW,
		_parent => PROP_RW
	]
};

sub CTOR {
	my ($this,$data,$parent) = @_;
	
	die ArgException->new( data => 'A hash reference is required' )
		unless ref($data) eq 'HASH';
		
	die ArgException->new( data => 'A hash must contain either scalars or subs')
		if ref($_) && ref($_) ne 'CODE', values %$data;
	
	$this->_data($data);
	$this->_parent($parent);
}

sub GetString {
	my ($this,$id,$args) = @_;
	
	if(my $format = $this->_data->{$id}) {
		return $this->FormatString($format,$args);
	} else {
		return $this->_parent? $this->_parent->GetString($id,$args) : "[ $id ]";
	}
	
}

sub AddFormat {
	my ($this,$id,$format) = @_;
	
	die ArgException->new( id => 'A format id is required' )
		unless $id;

	die ArgException->new( format => 'A format must be a scalar or a sub' )
		if ref($format) and ref($format) ne 'CODE';
		
	$this->_data->{$id} = $format;
}

sub FormatString {
	my ($self,$text,$args) = @_;
    
    $args ||= {};
    $resolver ||= \&_defaultResolver;
    $text ||= '';
    
    $string =~ s/%(\w+(?:\.\w+)*)%/$self->GetValue($args,$1,"\[$1\]")/ge;
    
    return $string;
	
}

sub GetValue {
	my ($self,$obj,$path,$default) = @_;
    
    foreach my $chunk (split /\./,$path) {
        return $default unless $obj;
        if (ref $obj eq 'HASH') {
            $obj = $obj->{$chunk};
        } else {
            $obj = $self->Resolve($obj,$chunk);
        }
    }
    return $obj||'<undef>';
}

sub Resolve {
	my ($self,$obj,$prop) = @_;
    
    return ( eval { $obj->can($prop) } ? $obj->$prop() : undef );
}

sub _LoadMap {
	my ($self,$file,$parent) = @_;
	
	my $data = do $file;
	my $e = $@;
	die Exception->new("Failed to load file '$file'", $e) if $e;
	die IOException->new("Failed to load file '$file'", $!) if not defined $data and $!;
	die Exception->new("Failed to load file '$file'", "A hash data is expected") unless ref($data) eq 'HASH';
	
	return $self->new($data,$parent);
}

1;

__END__

=pod 

=head1 NAME

C<IMPL::Web::Resources::StringMap>

=head1 SYNOPSIS

=begin code

use IMPL::require {
	StringMap => 'IMPL::Resources::StringMap'
};

my $data = {
	TitleLabel => 'Search results',
	ViewLabel => 'View %name%', # same as sub { $_[0]->Format('View %name%',$_[1]) } 
	ResultsCountLabel => sub {
		my ($self,$args) = @_;
		
		$args ||= {};
		
		if (not $args->{count}) {
			return "No items found";
		} elsif($args->{count} == 1) {
			return "Found one item";
		} else {
			return $self->Format('Found %count% items', $args);
		}
	}
}

my $def = StringMap->new({
	ResultsCountLabel => 'Found %count% items'
});

my $map = StringMap->new($data, $def);

print $map->GetString('TitleLabel');
print $map->GetString(ResultsCountLabel => { count => 0 }); # will print "No items found"


=end code

=head1 DESCRIPTION

=head1 MEMBERS

=cut