File Coverage

blib/lib/MARC/File.pm
Criterion Covered Total %
statement 47 74 63.5
branch 7 22 31.8
condition n/a
subroutine 10 17 58.8
pod 9 9 100.0
total 73 122 59.8


line stmt bran cond sub pod time code
1             package MARC::File;
2              
3             =head1 NAME
4              
5             MARC::File - Base class for files of MARC records
6              
7             =cut
8              
9 29     29   5026 use strict;
  29         44  
  29         923  
10 29     29   602 use integer;
  29         40  
  29         119  
11 29     29   10788 use MARC::File::Utils;
  29         144  
  29         865  
12              
13 29     29   135 use vars qw( $ERROR );
  29         37  
  29         2023  
14              
15             =head1 SYNOPSIS
16              
17             use MARC::File::USMARC;
18              
19             my $file = MARC::File::USMARC->in( $filename );
20              
21             while ( my $marc = $file->next() ) {
22             # Do something
23             }
24             $file->close();
25             undef $file;
26              
27             =head1 EXPORT
28              
29             None.
30              
31             =head1 METHODS
32              
33             =head2 in()
34              
35             Opens a file for import. Ordinarily you will use C
36             or C to do this.
37              
38             my $file = MARC::File::USMARC->in( 'file.marc' );
39              
40             Returns a C object, or C on failure. If you
41             encountered an error the error message will be stored in
42             C<$MARC::File::ERROR>.
43              
44             Optionally you can also pass in a filehandle, and C.
45             will "do the right thing".
46              
47             my $handle = IO::File->new( 'gunzip -c file.marc.gz |' );
48             my $file = MARC::File::USMARC->in( $handle );
49              
50             =cut
51              
52             sub in {
53 43     43 1 2291 my $class = shift;
54 43         80 my $arg = shift;
55 43         74 my ( $filename, $fh );
56              
57             ## if a valid filehandle was passed in
58 29     29   127 my $ishandle = do { no strict; defined fileno($arg); };
  29         47  
  29         15563  
  43         62  
  43         260  
59 43 100       130 if ( $ishandle ) {
60 11         17 $filename = scalar( $arg );
61 11         32 $fh = $arg;
62             }
63              
64             ## otherwise check if it's a filename, and
65             ## return undef if we weren't able to open it
66             else {
67 32         63 $filename = $arg;
68 32 50       53 $fh = eval { local *FH; open( FH, $arg ) or die; *FH{IO}; };
  32         78  
  32         1171  
  32         138  
69 32 50       133 if ( $@ ) {
70 0         0 $MARC::File::ERROR = "Couldn't open $filename: $@";
71 0         0 return;
72             }
73             ## all file streams are assumed to be utf8 if we have a modern perl
74             }
75              
76 43 50       145 utf8_safe() ? binmode( $fh, ':utf8' ) : binmode( $fh );
77 43         266 my $self = {
78             filename => $filename,
79             fh => $fh,
80             recnum => 0,
81             warnings => [],
82             };
83              
84 43         287 return( bless $self, $class );
85              
86             } # new()
87              
88             sub out {
89 0     0 1 0 die "Not yet written";
90             }
91              
92             =head2 next( [\&filter_func] )
93              
94             Reads the next record from the file handle passed in.
95              
96             The C<$filter_func> is a reference to a filtering function. Currently,
97             only USMARC records support this. See L's C
98             function for details.
99              
100             Returns a MARC::Record reference, or C on error.
101              
102             =cut
103              
104             sub next {
105 390     390 1 54706 my $self = shift;
106 390         677 $self->{recnum}++;
107 390 100       1146 my $rec = $self->_next() or return;
108 371         1575 return $self->decode($rec, @_);
109             }
110              
111             =head2 skip()
112              
113             Skips over the next record in the file. Same as C,
114             without the overhead of parsing a record you're going to throw away
115             anyway.
116              
117             Returns 1 or undef.
118              
119             =cut
120              
121             sub skip {
122 0     0 1 0 my $self = shift;
123 0 0       0 my $rec = $self->_next() or return;
124 0         0 return 1;
125             }
126              
127             =head2 warnings()
128              
129             Simlilar to the methods in L and L,
130             C will return any warnings that have accumulated while
131             processing this file; and as a side-effect will clear the warnings buffer.
132              
133             =cut
134              
135             sub warnings {
136 288     288 1 2179 my $self = shift;
137 288         294 my @warnings = @{ $self->{warnings} };
  288         596  
138 288         504 $self->{warnings} = [];
139 288         759 return(@warnings);
140             }
141              
142             =head2 close()
143              
144             Closes the file, both from the object's point of view, and the actual file.
145              
146             =cut
147              
148             sub close {
149 12     12 1 2392 my $self = shift;
150 12         167 close( $self->{fh} );
151 12         44 delete $self->{fh};
152 12         29 delete $self->{filename};
153 12         257 return;
154             }
155              
156             sub _unimplemented() {
157 0     0   0 my $self = shift;
158 0         0 my $method = shift;
159 0         0 warn "Method $method must be overridden";
160             }
161              
162             =head2 write()
163              
164             Writes a record to the output file. This method must be overridden
165             in your subclass.
166              
167             =head2 decode()
168              
169             Decodes a record into a USMARC format. This method must be overridden
170             in your subclass.
171              
172             =cut
173              
174 0     0 1 0 sub write { $_[0]->_unimplemented("write"); }
175 0     0 1 0 sub decode { $_[0]->_unimplemented("decode"); }
176              
177             # NOTE: _warn must be called as an object method
178              
179             sub _warn {
180 0     0   0 my ($self,$warning) = @_;
181 0         0 push( @{ $self->{warnings} }, "$warning in record ".$self->{recnum} );
  0         0  
182 0         0 return( $self );
183             }
184              
185             # NOTE: _gripe can be called as an object method, or not. Your choice.
186             # NOTE: it's use is now depracated use _warn instead
187             sub _gripe(@) {
188 0     0   0 my @parms = @_;
189 0 0       0 if ( @parms ) {
190 0         0 my $self = shift @parms;
191              
192 0 0       0 if ( ref($self) =~ /^MARC::File/ ) {
193 0 0       0 push( @parms, " at byte ", tell($self->{fh}) )
194             if $self->{fh};
195 0 0       0 push( @parms, " in file ", $self->{filename} ) if $self->{filename};
196             } else {
197 0         0 unshift( @parms, $self );
198             }
199              
200 0         0 $ERROR = join( "", @parms );
201 0         0 warn $ERROR;
202             }
203              
204 0         0 return;
205             }
206              
207             =head2 utf8_safe()
208              
209             Tells whether the version of Perl we're using is UFT8-safe.
210              
211             =cut
212              
213             sub utf8_safe {
214 5391     5391 1 23284 return 0; ## XXX eventually we should be able to handle utf8
215 0 0         return 1 if $] >= 5.008001;
216              
217 0           return 0;
218             }
219              
220             1;
221              
222             __END__