view Lib/IMPL/Resources/StringMap.pm @ 381:ced5937ff21a

Custom getters/setters support method names in theirs definitions Initial support for localizable labels in DOM schemas
author cin
date Wed, 22 Jan 2014 16:56:10 +0400
parents 2eed076cb944
children
line wrap: on
line source

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

use IMPL::Const qw(:prop);
use IMPL::declare {
	require => {
		Exception => 'IMPL::Exception',
		IOException => '-IMPL::IOException',
		ArgException => '-IMPL::InvalidArgumentException'
	},
	base => [
		'IMPL::Object' => '@_'
	],
	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 grep 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 ref($format) eq 'CODE' ? &$format($this,$args || {}) : $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 ||= {};
    $text ||= '';
    
    $text =~ s/%(\w+(?:\.\w+)*)%/$self->GetValue($args,$1,"\[$1\]")/ge;
    
    return $text;
	
}

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->$prop() };
}

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