Mercurial > pub > Impl
view Lib/IMPL/Transform.pm @ 374:6608db5dcb81
sync
author | cin |
---|---|
date | Thu, 09 Jan 2014 19:40:33 +0400 |
parents | 4ddb27ff4a0b |
children |
line wrap: on
line source
package IMPL::Transform; use strict; use parent qw(IMPL::Object); use IMPL::lang qw(:declare); BEGIN { public _direct property templates => PROP_ALL; public _direct property default => PROP_ALL; public _direct property plain => PROP_ALL; private _direct property _cache => PROP_ALL; } sub CTOR { my $this = shift; my $args = @_ == 1 ? shift : { @_ }; $this->{$plain} = delete $args->{-plain}; $this->{$default} = delete $args->{-default}; $this->{$templates} = $args; } sub Transform { my ($this,$object,@args) = @_; if (not ref $object) { die new IMPL::Exception("There is no the template for a plain value in the transform") unless $this->{$plain}; my $template = $this->{$plain}; return $this->$template($object,@args); } else { my $template = $this->MatchTemplate($object) || $this->default or die new IMPL::Transform::NoTransformException(ref $object); return $this->ProcessTemplate($template,$object,@args); } } sub MatchTemplate { my ($this,$object) = @_; my $class = $this->GetClassForObject( $object ); if (my $t = $this->{$_cache}->{$class} ) { return $t; } else { $t = $this->{$templates}->{$class}; return $this->{$_cache}->{$class} = $t if $t; { no strict 'refs'; my @isa = @{"${class}::ISA"}; while (@isa) { my $sclass = shift @isa; $t = $this->{$templates}->{$sclass}; #cache and return return $this->{$_cache}->{$class} = $t if $t; push @isa, @{"${sclass}::ISA"}; } ; }; } } sub ProcessTemplate { my ($this,$t,$obj,@args) = @_; return $this->$t($obj,@args); } sub GetClassForObject { my ($this,$object) = @_; return ref $object; } package IMPL::Transform::NoTransformException; use IMPL::declare { base => { 'IMPL::Exception' => sub { 'No transformation', @_ } } }; 1; __END__ =pod =head1 NAME C<IMPL::Transform> - преобразование объектной структуры =head1 SYNOPSIS =begin code my $obj = new AnyObject; my $t = new Transform ( SomeClass => sub { my ($this,$object) = @_; return new NewClass({ Name => $object->name, Document => $this->Transform($object->Data) }) }, DocClass => sub { my ($this,$object) = @_; return new DocPreview(Author => $object->Author, Text => $object->Data); }, -default => sub { my ($this,$object) = @_; return $object; }, -plain => sub { my ($this,$object) = @_; return $object; } ); my $result = $t->Transform($obj); =end code =head1 DESCRIPTION Преобразование одного объекта к другому, например даных к их представлению. =cut