File Coverage

blib/lib/MAB2/Parser/RAW.pm
Criterion Covered Total %
statement 62 62 100.0
branch 17 18 94.4
condition 2 3 66.6
subroutine 9 9 100.0
pod 2 2 100.0
total 92 94 97.8


line stmt bran cond sub pod time code
1             package MAB2::Parser::RAW;
2              
3             our $VERSION = '0.23';
4              
5 6     6   465 use strict;
  6         11  
  6         167  
6 6     6   30 use warnings;
  6         10  
  6         173  
7 6     6   29 use charnames qw< :full >;
  6         8  
  6         30  
8 6     6   975 use Carp qw(carp croak);
  6         12  
  6         259  
9 6     6   30 use Readonly;
  6         11  
  6         243  
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 5     5 1 3321 my $class = shift;
18 5         8 my $file = shift;
19              
20 5         22 my $self = {
21             filename => undef,
22             rec_number => 0,
23             reader => undef,
24             };
25              
26             # check for file or filehandle
27 5         9 my $ishandle = eval { fileno($file); };
  5         20  
28 5 100 66     113 if ( !$@ && defined $ishandle ) {
    100          
29 2         6 $self->{filename} = scalar $file;
30 2         6 $self->{reader} = $file;
31             }
32             elsif ( -e $file ) {
33 2 50   1   129 open $self->{reader}, '<:encoding(UTF-8)', $file
  1         10  
  1         2  
  1         6  
34             or croak "cannot read from file $file\n";
35 2         1226 $self->{filename} = $file;
36             }
37             else {
38 1         19 croak "file or filehande $file does not exists";
39             }
40 4         16 return ( bless $self, $class );
41             }
42              
43             sub next {
44 48     48 1 2624 my $self = shift;
45 48 100       900 if ( my $line = $self->{reader}->getline() ) {
46 46         1442 $self->{rec_number}++;
47 46         90 my $record = _decode($line);
48              
49             # get last subfield from 001 as id
50 46         64 my ($id) = map { $_->[-1] } grep { $_->[0] =~ '001' } @{$record};
  45         87  
  2082         2782  
  46         73  
51 46         181 return { _id => $id, record => $record };
52             }
53 2         44 return;
54             }
55              
56             sub _decode {
57 46     46   64 my $reader = shift;
58 46         106 chomp $reader;
59              
60 46 100       418 if ( substr( $reader, -1, 1 ) ne $END_OF_RECORD ) {
61 1         17 carp "record terminator not found";
62             }
63              
64 46         737 my @record;
65 46         92 my $leader = substr $reader, 0, $LEADER_LEN;
66 46 100       377 if ( $leader =~ m/(\d{5}\wM2.0\d*\s*\w)/ ) {
67 45         114 push @record, [ 'LDR', '', '_', $leader ];
68             }
69             else {
70 1         11 carp "faulty record leader: \"$leader\"";
71             }
72              
73 46         538 my @fields = split $END_OF_FIELD, substr( $reader, $LEADER_LEN, -1 );
74              
75 46         1409 for my $field (@fields) {
76              
77 2039 100       4068 if ( length $field <= 4 ) {
78 1         13 carp "faulty field: \"$field\"";
79 1         420 next;
80             }
81              
82 2038 100       6632 if ( my ( $tag, $ind, $data )
83             = $field =~ m/^(\d{3})([A-Za-z0-9\s])(.*)/ )
84             {
85 2037 100       4766 if ( $data =~ m/\s*$SUBFIELD_INDICATOR(.*)/ ) {
86             push(
87             @record,
88             [ $tag,
89             $ind,
90 109         769 map { ( substr( $_, 0, 1 ), substr( $_, 1 ) ) }
  169         1196  
91             split /$SUBFIELD_INDICATOR/,
92             $1
93             ]
94             );
95             }
96             else {
97 1928         12179 push @record, [ $tag, $ind, '_', $data ];
98             }
99             }
100             else {
101 1         11 carp "faulty field structure: \"$field\"";
102 1         422 next;
103             }
104              
105             }
106              
107 46         269 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