RSS Git Download  Clone
Raw Blame History
# same as Text::CSV::Simple, but changes default on_failure trigger to make stderr warning more explicit:

package Text_CSV_Simple_Base;

use Class::Trigger;
use Data::Dumper; 

__PACKAGE__->add_trigger(on_failure => sub { 
	my ($self, $csv) = @_;
	if (my $err = $csv->error_input) {
		warn qq!LIMS::Local::Text_CSV_Simple parser failed on "$err"\n!;
		# warn Dumper [$csv->error_diag]; # uncomment to dump error diagnostics
	}
});

package LIMS::Local::Text_CSV_Simple;

use base 'Text_CSV_Simple_Base';

$VERSION = '1.00';

use strict;

use Text::CSV_XS;
use File::Slurp ();

sub new {
	my $class = shift;
	return bless { _parser => Text::CSV_XS->new(@_), } => $class;
}

sub _parser { shift->{_parser} }

sub _file {
	my $self = shift;
	$self->{_file} = shift if @_;
	return $self->{_file};
}

sub _contents {
	my $self  = shift;
	my @lines = File::Slurp::read_file($self->_file)
		or die "Can't read " . $self->_file;
	return @lines;
}

sub want_fields {
	my $self = shift;
	if (@_) {
		$self->{_wanted} = [@_];
	}
	return @{ $self->{_wanted} || [] };
}

sub field_map {
	my $self = shift;
	if (@_) {
		$self->{_map} = [@_];
	}
	return @{ $self->{_map} || [] };
}

sub read_file {
	my ($self, $file) = @_;
	$self->_file($file);
	my @lines = $self->_contents;
	my @return;
	my $csv = $self->_parser;
	foreach my $line (@lines) {
		eval { $self->call_trigger(before_parse => $line) };
		next if $@;
		next unless $line;
		unless ($csv->parse($line)) {
			$self->call_trigger(on_failure => $csv);
			next;
		}
		my @fields = $csv->fields;
		eval { $self->call_trigger(after_parse => \@fields) };
		next if $@;
		if (my @wanted = $self->want_fields) {
			@fields = @fields[ $self->want_fields ];
		}
		my $addition = [ @fields ];
		if (my @map = $self->field_map) {
			my $hash = { map { $_ => shift @fields } @map };
			delete $hash->{null};
			$addition = $hash;
		} 
		eval { $self->call_trigger(after_processing => $addition) };
		next if $@;
		push @return, $addition;
	}
	return @return;
}