File Coverage

blib/lib/MAB2/Parser/RAW.pm
Criterion Covered Total %
statement 15 59 25.4
branch 0 18 0.0
condition 0 3 0.0
subroutine 5 8 62.5
pod 2 2 100.0
total 22 90 24.4


line stmt bran cond sub pod time code
1             package MAB2::Parser::RAW;
2              
3             our $VERSION = '0.21';
4              
5 6     6   307 use strict;
  6         14  
  6         175  
6 6     6   31 use warnings;
  6         11  
  6         199  
7 6     6   27 use charnames qw< :full >;
  6         9  
  6         29  
8 6     6   955 use Carp qw(carp croak);
  6         12  
  6         275  
9 6     6   30 use Readonly;
  6         8  
  6         258  
10              
11             Readonly my $LEADER_LEN => 24;
12             Readonly my $SUBFIELD_INDICATOR => qq{\N{INFORMATION SEPARATOR ONE}};
13             Readonly my $END_OF_FIELD => qq{\N{INFORMATION SEPARATOR TWO}};
14             Readonly my $END_OF_RECORD => qq{\N{INFORMATION SEPARATOR THREE}};
15              
16             sub new {
17 0     0 1   my $class = shift;
18 0           my $file = shift;
19              
20 0           my $self = {
21             filename => undef,
22             rec_number => 0,
23             reader => undef,
24             };
25              
26             # check for file or filehandle
27 0           my $ishandle = eval { fileno($file); };
  0            
28 0 0 0       if ( !$@ && defined $ishandle ) {
    0          
29 0           $self->{filename} = scalar $file;
30 0           $self->{reader} = $file;
31             }
32             elsif ( -e $file ) {
33 0 0         open $self->{reader}, '<:encoding(UTF-8)', $file
34             or croak "cannot read from file $file\n";
35 0           $self->{filename} = $file;
36             }
37             else {
38 0           croak "file or filehande $file does not exists";
39             }
40 0           return ( bless $self, $class );
41             }
42              
43             sub next {
44 0     0 1   my $self = shift;
45 0 0         if ( my $line = $self->{reader}->getline() ) {
46 0           $self->{rec_number}++;
47 0           my $record = _decode($line);
48              
49             # get last subfield from 001 as id
50 0           my ($id) = map { $_->[-1] } grep { $_->[0] =~ '001' } @{$record};
  0            
  0            
  0            
51 0           return { _id => $id, record => $record };
52             }
53 0           return;
54             }
55              
56             sub _decode {
57 0     0     my $reader = shift;
58 0           chomp $reader;
59              
60 0 0         if ( substr( $reader, -1, 1 ) ne $END_OF_RECORD ) {
61 0           carp "record terminator not found";
62             }
63              
64 0           my @record;
65 0           my $leader = substr $reader, 0, $LEADER_LEN;
66 0 0         if ( $leader =~ m/(\d{5}\wM2.0\d*\s*\w)/ ) {
67 0           push @record, [ 'LDR', '', '_', $leader ];
68             }
69             else {
70 0           carp "faulty record leader: \"$leader\"";
71             }
72              
73 0           my @fields = split $END_OF_FIELD, substr( $reader, $LEADER_LEN, -1 );
74              
75 0           for my $field (@fields) {
76              
77 0 0         if ( length $field <= 4 ) {
78 0           carp "faulty field: \"$field\"";
79 0           next;
80             }
81              
82 0 0         if ( my ( $tag, $ind, $data )
83             = $field =~ m/^(\d{3})([A-Za-z0-9\s])(.*)/ )
84             {
85 0 0         if ( $data =~ m/\s*$SUBFIELD_INDICATOR(.*)/ ) {
86             push(
87             @record,
88             [ $tag,
89             $ind,
90 0           map { ( substr( $_, 0, 1 ), substr( $_, 1 ) ) }
  0            
91             split /$SUBFIELD_INDICATOR/,
92             $1
93             ]
94             );
95             }
96             else {
97 0           push @record, [ $tag, $ind, '_', $data ];
98             }
99             }
100             else {
101 0           carp "faulty field structure: \"$field\"";
102 0           next;
103             }
104              
105             }
106              
107 0           return \@record;
108             }
109              
110             1; # End of MAB2::Parser::RAW
111              
112             __END__
113              
114             =pod
115              
116             =encoding UTF-8
117              
118             =head1 NAME
119              
120             MAB2::Parser::RAW - MAB2 RAW format parser
121              
122             =head1 SYNOPSIS
123              
124             L<MAB2::Parser::RAW> is a parser for raw MAB2 records.
125              
126             L<MAB2::Parser::RAW> expects UTF-8 encoded files as input. Otherwise provide a
127             filehande with a specified I/O layer.
128              
129             use MAB2::Parser::RAW;
130              
131             my $parser = MAB2::Parser::RAW->new( $filename );
132              
133             while ( my $record_hash = $parser->next() ) {
134             # do something
135             }
136              
137             =head1 Arguments
138              
139             =over
140              
141             =item C<file>
142              
143             Path to file with MAB2 Band records.
144              
145             =item C<fh>
146              
147             Open filehandle for file with MAB2 Band records.
148              
149             =back
150              
151             =head1 METHODS
152              
153             =head2 new($filename | $filehandle)
154              
155             =head2 next()
156              
157             Reads the next record from MAB2 input stream. Returns a Perl hash.
158              
159             =head2 _decode($record)
160              
161             Deserialize a raw MAB2 record to an ARRAY of ARRAYs.
162              
163             =head1 SEEALSO
164              
165             L<Catmandu::Importer::MAB2>.
166              
167             =head1 AUTHOR
168              
169             Johann Rolschewski <jorol@cpan.org>
170              
171             =head1 COPYRIGHT AND LICENSE
172              
173             This software is copyright (c) 2013 by Johann Rolschewski.
174              
175             This is free software; you can redistribute it and/or modify it under
176             the same terms as the Perl 5 programming language system itself.
177              
178             =cut