Mercurial > pub > Impl
diff Lib/IMPL/DOM/Transform/ObjectToDOM.pm @ 236:2904da230022
DOM refactoring
author | sergey |
---|---|
date | Mon, 15 Oct 2012 04:23:01 +0400 |
parents | |
children | 61db68166c37 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/IMPL/DOM/Transform/ObjectToDOM.pm Mon Oct 15 04:23:01 2012 +0400 @@ -0,0 +1,134 @@ +package IMPL::DOM::Transform::ObjectToDOM; +use strict; + +use IMPL::Const qw(:prop :access); +use IMPL::declare { + require => { + PropertyInfo => 'IMPL::Class::PropertyInfo', + Builder => 'IMPL::DOM::Navigator::Builder', + Exception => 'IMPL::Exception', + ArgumentException => '-IMPL::InvalidArgumentException', + OperationException => '-IMPL::InvalidOperationException' + }, + base => [ + 'IMPL::Transform' => sub { + -plain => \&TransformPlain, + HASH => \&TransformHash, + -default => \&TransformDefault + } + ], + props => [ + documentSchema => PROP_RO, + _schema => PROP_RW, + _navi => PROP_RW + ] +}; + +sub CTOR { + my ($this,$docName,$docSchema) = @_; + + my $docNodeSchema = $docSchema->selectSingleNode(sub { $_->name eq $docName }) + or die OperationException->new("Can't find a node schema for the document '$docName'"); + + my $docClass = ($docNodeSchema->can('nativeType') ? $docNodeSchema->nativeType : undef) || 'IMPL::DOM::Document'; + + $this->documentSchema($docNodeSchema); + + $this->_navi( + Builder->new( + $docClass, + $docSchema, + ignoreUndefined => 1 + ) + ); + $this->_schema($docSchema); + + $this->_navi->NavigateCreate($docName); +} + +sub TransformPlain { + my ($this,$data) = @_; + + $this->_navi->Current->nodeValue( $this->_navi->inflateValue($data) ); + return $this->_navi->Current; +} + +sub TransformHash { + my ($this,$data) = @_; + + die ArgumentException->new(data => 'A HASH reference is required') + unless ref $data eq 'HASH'; + + KEYLOOP: foreach my $key (keys %$data) { + my $value = $data->{$key}; + + if (ref $value eq 'ARRAY') { + foreach my $subval (@$value) { + + my $node = $this->_navi->NavigateCreate($key); + + unless(defined $node) { + $this->_navi->Back(); + next KEYLOOP; + } + + $this->Transform($subval); + + $this->_navi->Back(); + } + } else { + my $node = $this->_navi->NavigateCreate($key); + + unless(defined $node) { + $this->_navi->Back(); + next KEYLOOP; + } + + $this->Transform($value); + + $this->_navi->Back(); + } + } + return $this->_navi->Current; +} + +sub TransformDefault { + my ($this,$data) = @_; + + if ( ref $data and eval { $data->can('GetMeta') } ) { + my %props = map { + $_->name, 1 + } $data->GetMeta(PropertyInfo, sub { $_->access == ACCESS_PUBLIC }, 1 ); + + my %values = map { + $_, + $data->$_(); + } keys %props; + + return $this->Transform(\%values); + } else { + die OperationException->new("Don't know how to transform $data"); + } + + return $this->_navi->Current; +} + +sub buildErrors { + my ($this) = @_; + + return $this->_navi->buildErrors; +} + +1; + +__END__ + +=pod + +=head1 NAME + +C<IMPL::DOM::Transform::ObjectToDOM> -преобразование объекта + +=head1 SYNOPSIS + +=cut \ No newline at end of file