Mercurial > pub > Impl
view Lib/IMPL/DOM/Transform/ObjectToDOM.pm @ 246:2746a8e5a6c4
Fixed regressions in DOM due previous refactorings
Fixed ObjectToDOM transformation to handle a schema with mixed node types
author | sergey |
---|---|
date | Tue, 30 Oct 2012 01:17:31 +0400 |
parents | 61db68166c37 |
children | 129e48bb5afb |
line wrap: on
line source
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 ] }; use constant { SchemaNode => 'IMPL::DOM::Schema::Node' }; sub CTOR { my ($this,$docName,$docSchema,$transforms) = @_; my $docNodeSchema = $docSchema->selectSingleNode(sub { $_->isa(SchemaNode) and $_->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