X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/blobdiff_plain/45119ead56cbc3b06daae7ea258b3839234e0b9a..af2053931fb484b246ba42f93df4889c4257ab42:/SL/Helper/Csv/Dispatcher.pm diff --git a/SL/Helper/Csv/Dispatcher.pm b/SL/Helper/Csv/Dispatcher.pm index 9626fed25..17d52d751 100644 --- a/SL/Helper/Csv/Dispatcher.pm +++ b/SL/Helper/Csv/Dispatcher.pm @@ -9,6 +9,8 @@ use Rose::Object::MakeMethods::Generic scalar => [ qw( _specs _errors ) ]; +use SL::Helper::Csv::Error; + sub new { my ($class, $parent) = @_; my $self = bless { }, $class; @@ -20,13 +22,67 @@ sub new { } sub dispatch { - my ($self, $obj, $line) = @_; + my ($self, $line) = @_; + + my $class = $self->_class_by_line($line); + croak 'no class given' unless $class; + + eval "require " . $class; + my $obj = $class->new; - for my $spec (@{ $self->_specs }) { + my $specs = $self->_specs_by_line($line); + for my $spec (@{ $specs }) { $self->apply($obj, $spec, $line->{$spec->{key}}); } + + return $obj; +} + +# return class for given line +# if only one profile is given, return this profiles class +# if more than one profile is given, identify class by first +# column??? +sub _class_by_line { + my ($self, $line) = @_; + + my $class; + if ($self->_csv->is_multiplexed) { + foreach my $p (@{ $self->_csv->profile }) { + my $row_ident = $p->{row_ident}; + if ($line->{datatype} eq $row_ident) { + $class = $p->{class}; + last; + } + } + } else { + $class = @{ $self->_csv->profile }[0]->{class}; + } + + return $class; +} + +sub _specs_by_line { + my ($self, $line) = @_; + + my $spec; + my $i = 0; + if ($self->_csv->is_multiplexed) { + foreach my $p (@{ $self->_csv->profile }) { + my $row_ident = $p->{row_ident}; + if ($line->{datatype} eq $row_ident) { + $spec = @{ $self->_specs }[$i]; + last; + } + $i++; + } + } else { + $spec = @{ $self->_specs }[0]; + } + + return $spec; } + sub apply { my ($self, $obj, $spec, $value) = @_; return unless $value; @@ -36,7 +92,6 @@ sub apply { if ($class) { # autovifify - eval "require $class; 1" or die "could not load class '$class'"; if (defined $index) { if (! $obj->$acc || !$obj->$acc->[$index]) { my @objects = $obj->$acc; @@ -64,25 +119,70 @@ sub is_known { sub parse_profile { my ($self, %params) = @_; - my $header = $self->_csv->header; - my $profile = $self->_csv->profile; + my $profile; + my $class; + my $header; + my @specs; + + my $i = 0; + foreach my $h (@{ $self->_csv->header }) { + $header = $h; + if ($self->_csv->profile) { + $profile = @{ $self->_csv->profile }[$i]->{profile}; + $class = @{ $self->_csv->profile }[$i]->{class}; + } + + my $spec = $self->_parse_profile(profile => $profile, + class => $class, + header => $header); + push @specs, $spec; + $i++; + } + + $self->_specs(\@specs); + + return ! $self->errors; +} + +sub _parse_profile { + my ($self, %params) = @_; + + my $profile = $params{profile}; + my $class = $params{class}; + my $header = $params{header}; + my @specs; for my $col (@$header) { next unless $col; - push @specs, $self->make_spec($col, $profile->{$col} || $col); + if ($self->_csv->strict_profile) { + if (exists $profile->{$col}) { + push @specs, $self->make_spec($col, $profile->{$col}, $class); + } else { + $self->unknown_column($col, undef); + } + } else { + if (exists $profile->{$col}) { + push @specs, $self->make_spec($col, $profile->{$col}, $class); + } else { + push @specs, $self->make_spec($col, $col, $class); + } + } } - $self->_specs(\@specs); $self->_csv->_push_error($self->errors); - return ! $self->errors; + + return \@specs; } sub make_spec { - my ($self, $col, $path) = @_; + my ($self, $col, $path, $cur_class) = @_; my $spec = { key => $col, steps => [] }; - my $cur_class = $self->_csv->class; + + return unless $path; + + return unless $cur_class; for my $step_index ( split /\.(?!\d)/, $path ) { my ($step, $index) = split /\./, $step_index; @@ -101,6 +201,7 @@ sub make_spec { my $next_class = $cur_class->meta->relationship($step)->class; push @{ $spec->{steps} }, [ $step, $next_class, $index ]; $cur_class = $next_class; + eval "require $cur_class; 1" or die "could not load class '$cur_class'"; } } else { # simple dispatch push @{ $spec->{steps} }, [ $step ]; @@ -137,7 +238,7 @@ sub errors { sub _push_error { my ($self, @errors) = @_; - my @new_errors = ($self->errors, @errors); + my @new_errors = ($self->errors, map { SL::Helper::Csv::Error->new(@$_) } @errors); $self->_errors(\@new_errors); }