use Data::Dumper;
use Carp;
use Scalar::Util qw(weaken);
+use List::MoreUtils qw(all pairwise);
use Rose::Object::MakeMethods::Generic scalar => [ qw(
- _specs _errors
+ _specs _row_class _row_spec _errors
) ];
use SL::Helper::Csv::Error;
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;
+ # initialize lookup hash if not already done
+ if ($self->_csv->is_multiplexed && ! defined $self->_row_class ) {
+ $self->_row_class({ map { $_->{row_ident} => $_->{class} } @{ $self->_csv->profile } });
+ }
+
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;
- }
- }
+ return $self->_row_class->{$line->{datatype}};
} else {
- $class = $self->_csv->profile->[0]->{class};
+ return $self->_csv->profile->[0]->{class};
}
-
- return $class;
}
sub _specs_by_line {
my ($self, $line) = @_;
- my $spec;
- my $i = 0;
+ # initialize lookup hash if not already done
+ if ($self->_csv->is_multiplexed && ! defined $self->_row_spec ) {
+ $self->_row_spec({ pairwise { no warnings 'once'; $a->{row_ident} => $b } @{ $self->_csv->profile }, @{ $self->_specs } });
+ }
+
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++;
- }
+ return $self->_row_spec->{$line->{datatype}};
} else {
- $spec = $self->_specs->[0];
+ return $self->_specs->[0];
}
-
- return $spec;
}
}
sub is_known {
- my ($self, $col) = @_;
- return grep { $col eq $_->{key} } $self->_specs;
+ my ($self, $col, $row) = @_;
+ return grep { $col eq $_->{key} } @{ $self->_specs->[$row // 0] };
}
sub parse_profile {
my ($self, %params) = @_;
- my $profile;
- my $class;
- my $header;
my @specs;
+ my $csv_profile = $self->_csv->profile;
+ my $h_aref = ($self->_csv->is_multiplexed)? $self->_csv->header : [ $self->_csv->header ];
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,
+ foreach my $header (@{ $h_aref }) {
+ my $spec = $self->_parse_profile(profile => $csv_profile->[$i]->{profile},
+ mapping => $csv_profile->[$i]->{mapping},
+ class => $csv_profile->[$i]->{class},
header => $header);
push @specs, $spec;
$i++;
$self->_specs(\@specs);
+ $self->_csv->_push_error($self->errors);
+
return ! $self->errors;
}
sub _parse_profile {
my ($self, %params) = @_;
- my $profile = $params{profile};
+ my $profile = $params{profile} // {};
my $class = $params{class};
my $header = $params{header};
+ my $mapping = $params{mapping};
my @specs;
for my $col (@$header) {
next unless $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);
- }
+ if (exists $mapping->{$col} && $profile->{$mapping->{$col}}) {
+ push @specs, $self->make_spec($col, $profile->{$mapping->{$col}}, $class);
+ } elsif (exists $mapping->{$col} && !%{ $profile }) {
+ push @specs, $self->make_spec($col, $mapping->{$col}, $class);
+ } elsif (exists $profile->{$col}) {
+ push @specs, $self->make_spec($col, $profile->{$col}, $class);
} else {
- if (exists $profile->{$col}) {
- push @specs, $self->make_spec($col, $profile->{$col}, $class);
+ if ($self->_csv->strict_profile) {
+ $self->unknown_column($col, undef);
} else {
push @specs, $self->make_spec($col, $col, $class);
}
}
}
- $self->_csv->_push_error($self->errors);
-
return \@specs;
}
sub make_spec {
my ($self, $col, $path, $cur_class) = @_;
- my $spec = { key => $col, steps => [] };
+ my $spec = { key => $col, path => $path, steps => [] };
return unless $path;