File Coverage

blib/lib/MAB2/Parser/Disk.pm
Criterion Covered Total %
statement 15 59 25.4
branch 0 16 0.0
condition 0 3 0.0
subroutine 5 8 62.5
pod 2 2 100.0
total 22 88 25.0


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