File Coverage

blib/lib/Net/OAI/ListRecords.pm
Criterion Covered Total %
statement 88 94 93.6
branch 36 40 90.0
condition 1 3 33.3
subroutine 15 18 83.3
pod 8 8 100.0
total 148 163 90.8


line stmt bran cond sub pod time code
1             package Net::OAI::ListRecords;
2              
3 17     17   89 use strict;
  17         35  
  17         442  
4 17     17   87 use warnings;
  17         30  
  17         522  
5 17     17   130 use base qw( XML::SAX::Base Net::OAI::Base );
  17         37  
  17         1667  
6 17     17   85 use Carp qw( croak );
  17         28  
  17         853  
7 17     17   9331 use Net::OAI::Record;
  17         40  
  17         453  
8 17     17   93 use Net::OAI::Record::Header;
  17         35  
  17         391  
9 17     17   87 use File::Temp qw( tempfile );
  17         31  
  17         880  
10 17     17   85 use Storable qw( store_fd fd_retrieve );
  17         28  
  17         709  
11 17     17   83 use IO::File;
  17         44  
  17         19771  
12              
13             =head1 NAME
14              
15             Net::OAI::ListRecords - Results of the ListRecords OAI-PMH verb.
16              
17             =head1 SYNOPSIS
18              
19             =head1 DESCRIPTION
20              
21             =head1 METHODS
22              
23             Like all responses to OAI verbs, ListRecords is based on L
24             and inherits its methods.
25              
26              
27             =head2 new()
28              
29             You probably don't want to be using this method yourself, since
30             Net::OAI::Harvester::listRecords() calls it for you.
31              
32             =cut
33              
34             sub new {
35 9     9 1 89 my ( $class, %opts ) = @_;
36              
37 9         30 my $package;
38 9 100       89 if ( $package = $opts{ recordHandler } ) {
    100          
39 2 50       17 $opts{ metadataHandler } and croak( "you may pass either a recordHandler or a metadataHandler to getRecord()" );
40 2         11 delete $opts { metadataHandler };
41             } elsif ( $package = $opts{ metadataHandler } ) {
42 3         12 delete $opts{ recordHandler };
43             } else {
44 4         14 delete $opts{ recordHandler };
45 4         19 $package = $opts{ metadataHandler } = 'Net::OAI::Record::OAI_DC';
46             }
47 9         65 Net::OAI::Harvester::_verifyHandler( $package );
48              
49 9   33     111 my $self = bless \%opts, ref( $class ) || $class;
50 9         84 my ( $fh, $tempfile ) = tempfile(UNLINK => 1);
51 9         7259 binmode( $fh, ':utf8' );
52 9         137 $self->{ recordsFileHandle } = $fh;
53 9         39 $self->{ recordsFilename } = $tempfile;
54              
55             ## so we can store code refs
56 9         28 $Storable::Deparse = 1;
57 9         28 $Storable::Eval = 1;
58              
59 9         37 $self->{ _prefixmap } = {};
60 9         58 return( $self );
61             }
62              
63             =head2 next()
64              
65             Returns the L object for the next OAI record in the
66             response, C if none remain. resumptionToken handling is performed
67             automagically if the original request was listAllIdentifiers().
68              
69             =cut
70              
71             sub next {
72 1207     1207 1 706040 my $self = shift;
73              
74             ## if we haven't opened our object store do it now
75 1207 100       3978 if ( ! $self->{ recordsFileHandle } ) {
76             $self->{ recordsFileHandle } = IO::File->new( $self->{ recordsFilename } )
77 7 50       76 or croak "unable to open temp file: ".$self->{ recordsFilename };
78             ## we assume utf8 encoding (perhaps wrongly)
79 7         869 binmode( $self->{ recordsFileHandle }, ':utf8' );
80             }
81              
82             ## no more data to read back from our object store then return undef
83 1207 100       4365 if ( $self->{ recordsFileHandle }->eof() ) {
84             $self->{ recordsFileHandle }->close() or croak "Could not close() ".$self->{ recordsFilename }
85 6 50       154 .". File system full?";
86 6         600 return( $self->handleResumptionToken( 'listRecords' ) );
87             }
88              
89             ## get an object back from the store, thaw and return it
90 1201         10555 my $record = fd_retrieve( $self->{ recordsFileHandle } );
91 1201         210562 return( $record );
92             }
93              
94             =head2 metadataHandler()
95             =head2 recordHandler()
96              
97             Returns the name of the package being used to represent the individual metadata
98             records. If unspecified it defaults to L which
99             should be ok.
100              
101             =cut
102              
103             sub metadataHandler {
104 0     0 1 0 my $self = shift;
105 0         0 return( $self->{ metadataHandler } );
106             }
107              
108             sub recordHandler {
109 0     0 1 0 my $self = shift;
110 0         0 return( $self->{ recordHandler } );
111             }
112              
113             ## SAX Handlers
114              
115             sub start_prefix_mapping {
116 4218     4218 1 59125 my ($self, $mapping) = @_;
117 4218 100       10904 if ( $self->get_handler() ) {
118 4200         35956 return $self->SUPER::start_prefix_mapping( $mapping )};
119 18         250 $self->{ _prefixmap }->{$mapping->{ Prefix }} = $mapping;
120             }
121              
122             sub end_prefix_mapping {
123 4218     4218 1 138647 my ($self, $mapping) = @_;
124 4218 100       11614 if ( $self->get_handler() ) {
125 4200         38039 return $self->SUPER::end_prefix_mapping( $mapping )};
126 18         211 delete $self->{ _prefixmap }->{$mapping->{ Prefix }};
127             }
128              
129             sub start_element {
130 41632     41632 1 258625 my ( $self, $element ) = @_;
131 41632 100       147139 return $self->SUPER::start_element( $element ) unless $element->{NamespaceURI} eq Net::OAI::Harvester::XMLNS_OAI;
132              
133             ## if we are at the start of a new record then we need an empty
134             ## metadata object to fill up
135 8816 100       27084 if ( $element->{ LocalName } eq 'record' ) {
    100          
136             ## we store existing downstream handler so we can replace
137             ## it after we are done retrieving the metadata record
138 1400         4550 $self->{ OLD_Handler } = $self->get_handler();
139             my $header = $self->{ recordHandler }
140             ? Net::OAI::Record::Header->new(
141             Handler => (ref($self->{ recordHandler }) ? $self->{ recordHandler } : $self->{ recordHandler }->new()),
142             fwdAll => 1,
143             )
144             : Net::OAI::Record::Header->new(
145 1400 100       18961 Handler => (ref($self->{ metadataHandler }) ? $self->{ metadataHandler } : $self->{ metadataHandler }->new()),
    100          
    50          
    100          
146             ($Net::OAI::Harvester::OLDmetadataHandler ? (fwdAll => 1) : ()),
147             );
148 1400         4761 $self->set_handler( $header );
149 1400         16791 foreach my $mapping ( values %{$self->{_prefixmap}} ) {
  1400         4708  
150 2800         40579 $self->SUPER::start_prefix_mapping($mapping)};
151             }
152             elsif ( $element->{ LocalName } eq 'ListRecords' ) {
153             }
154 8816         33254 return $self->SUPER::start_element( $element );
155             }
156              
157             sub end_element {
158 41632     41632 1 249632 my ( $self, $element ) = @_;
159              
160 41632         101106 $self->SUPER::end_element( $element );
161 41632 100       195865 return unless $element->{NamespaceURI} eq Net::OAI::Harvester::XMLNS_OAI;
162              
163             ## if we've got to the end of the record we need to stash
164             ## away the object in our object store on disk
165 8816 100       45322 if ( $element->{ LocalName } eq 'record' ) {
    100          
166              
167             ## we need to swap out the existing metadata handler and freeze
168             ## it on disk
169 1400         4031 my $header = $self->get_handler();
170 1400         11700 my $data = $header->get_handler();
171 1400         11982 $header->set_handler( undef ); ## remove reference to $record
172              
173             ## set handler to what is was before we started processing
174             ## the record
175 1400         31180 $self->set_handler( $self->{ OLD_Handler } );
176 1400         20988 my $record;
177 1400 100       3500 if ( $self->{ recordHandler } ) {
178 400         2342 $record = Net::OAI::Record->new(header => $header, recorddata => $data)
179             } else {
180 1000         5260 $record = Net::OAI::Record->new(header => $header, metadata => $data)
181             };
182              
183             ## commit the object to disk
184 1400         7725 Net::OAI::Harvester::debug( "committing record to object store" );
185 1400         7112 store_fd( $record, $self->{ recordsFileHandle } );
186             }
187              
188             ## otherwise if we got to the end of our list we can close
189             ## our object stash on disk
190             elsif ( $element->{ LocalName } eq 'ListRecords' ) {
191 7         87 $self->{ recordsFileHandle }->close();
192 7         972 $self->{ recordsFileHandle } = undef;
193             }
194              
195             }
196              
197             sub _fatal {
198 0     0     print STDERR "fatal: ", shift, "\n";
199 0           exit(1);
200             }
201              
202             1;
203