use Carp;
use IO::File;
use Params::Validate qw(:all);
-use List::MoreUtils qw(all);
+use List::MoreUtils qw(all pairwise);
use Text::CSV_XS;
use Rose::Object::MakeMethods::Generic scalar => [ qw(
file encoding sep_char quote_char escape_char header profile
numberformat dateformat ignore_unknown_columns strict_profile is_multiplexed
- _io _csv _objects _parsed _data _errors all_cvar_configs case_insensitive_header
+ _row_header _io _csv _objects _parsed _data _errors all_cvar_configs case_insensitive_header
) ];
use SL::Helper::Csv::Dispatcher;
if (scalar @profile > 1) {
# Each profile needs a class and a row_ident
my $info_ok = all { defined $_->{class} && defined $_->{row_ident} } @profile;
+ $self->_push_error([
+ 0,
+ "missing class or row_ident in one of the profiles for multiplexed data",
+ 0,
+ 0]) unless $info_ok;
# If header is given, there need to be a header for each profile
# and no empty headers.
if ($info_ok && $self->header) {
my @header = @{ $self->header };
- $info_ok = $info_ok && scalar @profile == scalar @header;
- $info_ok = $info_ok && all { scalar @$_ > 0} @header;
+ my $t_ok = scalar @profile == scalar @header;
+ $self->_push_error([
+ 0,
+ "number of headers and number of profiles must be the same for multiplexed data",
+ 0,
+ 0]) unless $t_ok;
+ $info_ok = $info_ok && $t_ok;
+
+ $t_ok = all { scalar @$_ > 0} @header;
+ $self->_push_error([
+ 0,
+ "no empty headers are allowed for multiplexed data",
+ 0,
+ 0]) unless $t_ok;
+ $info_ok = $info_ok && $t_ok;
}
$self->is_multiplexed($info_ok);
return $info_ok;
# mopst likely meant that field, so rewrite the header
if ($self->case_insensitive_header) {
die 'case_insensitive_header is only possible with profile' unless $self->profile;
- my @names = (
- keys %{ $self->profile || {} },
- );
- for my $name (@names) {
- for my $i (0..$#$header) {
- $header->[$i] = $name if lc $header->[$i] eq lc $name;
+ if ($header) {
+ my $p_num = 0;
+ foreach my $h (@{ $header }) {
+ my @names = (
+ keys %{ $self->profile->[$p_num]->{profile} || {} },
+ );
+ for my $name (@names) {
+ for my $i (0..$#$h) {
+ $h->[$i] = $name if lc $h->[$i] eq lc $name;
+ }
+ }
+ $p_num++;
}
}
}
sub _header_by_row {
my ($self, $row) = @_;
- my @header = @{ $self->header };
+ # initialize lookup hash if not already done
+ if ($self->is_multiplexed && ! defined $self->_row_header ) {
+ $self->_row_header({ pairwise { no warnings 'once'; $a->{row_ident} => $b } @{ $self->profile }, @{ $self->header } });
+ }
+
if ($self->is_multiplexed) {
- my $i = 0;
- foreach my $profile (@{ $self->profile }) {
- if ($row->[0] eq $profile->{row_ident}) {
- return $header[$i];
- }
- $i++;
- }
+ return $self->_row_header->{$row->[0]}
} else {
- return $header[0];
+ return $self->header->[0];
}
}
will have to do that for yourself. Since you provided the profile, it is
assumed you know what to do in this case.
+If no profile is given, any header field found will be taken as is.
+
+If the path in a profile entry is empty, the field will be subjected to
+C<strict_profile> and C<case_insensitive_header> checking, will be parsed into
+C<get_data>, but will not be attempted to be dispatched into objects.
+
If C<class> is present, the line will be handed to the new sub of this class,
and the return value used instead of the line itself.