Biblio-COUNTER
view release on metacpan or search on metacpan
lib/Biblio/COUNTER.pm view on Meta::CPAN
package Biblio::COUNTER;
use Biblio::COUNTER::Report;
use warnings;
use strict;
use vars qw($VERSION);
$VERSION = '0.11';
sub report {
my ($cls, $how, %args) = @_;
if (ref($how) eq 'ARRAY') {
die "Instantiating a report from an array not yet implemented";
}
elsif (ref($how)) {
# Read report from a filehandle
my $fh = $how;
my $callbacks = delete($args{'callback'}) || {};
my $report = Biblio::COUNTER::Report->new(
%args,
'fh' => $fh,
'callback' => {
'output' => sub {
my ($self, $output) = @_;
print $output, "\n";
},
%$callbacks,
},
'rows' => [],
'errors' => 0,
'warnings' => 0,
# Current position within the report
'r' => 0,
'c' => '',
# Current scope (REPORT, HEADER, or RECORD)
'scope' => undef,
# Current field (NAME, DESCRIPTION, etc. or TITLE, PUBLISHER, etc.)
'field' => undef,
# Containers
'report' => undef,
'header' => undef,
'record' => undef,
'container' => undef, # Current container
);
}
else {
# Instantiate a named report, e.g., "Journal Report 1 (R2)"
my $name = $how;
my ($genre, $number, $release) = $cls->_parse_report_name($name);
die "Unrecognized report type: $name"
unless defined $genre;
# Create the "model" object
$cls = "Biblio::COUNTER::Report::Release${release}::${genre}Report${number}";
die "Unimplemented report type: $name"
unless eval "use $cls; 1";
return $cls->new(%args);
}
}
sub _parse_report_name {
my ($cls, $name) = @_;
my ($genre, $number, $release);
if ($name =~ s/^\s*(Journal|Database|Book)\s+Report\s+(\w+)\s*//) {
($genre, $number) = ($1, $2);
}
else {
return;
}
if ($name =~ /^\(R?(\d+[a-z]?)\)/) {
$release = $1;
}
else {
$release = 2; # XXX Safe to default?
}
return ($genre, $number, $release);
}
1;
=pod
=head1 NAME
Biblio::COUNTER - COUNTER Codes of Practice report processing
lib/Biblio/COUNTER.pm view on Meta::CPAN
Each I<$code> must be a coderef, not the name of a function or method.
If an event is not specified in this hash, then the default action for the
event will be taken.
=back
=item B<name>
Get or set the report's name: this is the official name defined by the COUNTER
codes of practice. See L<REPORTS SUPPORTED> for a complete list of the
reports supported by this verison of L<Biblio::COUNTER|Biblio::COUNTER>.
=item B<code>
Get or set the report's code: this is the short string (e.g., C<JR1>)
that identifies the type, B<but not the version>, of a COUNTER report.
=item B<description>
Get or set the report's description: this is the official description
defined by the COUNTER codes of practice. For example, the C<Journal
Report 1 (R2)> report has the description C<Number of Successful
Full-Text Article Requests by Month and Journal>.
=item B<date_run>
Get or set the date on which the report was run. The date, if valid, is in
the ISO8601 standard form C<YYYY-MM-DD>.
=item B<criteria>
Get or set the report criteria. This is a free text field.
=item B<periods>
Get or set the periods for which the report contains counts. To
simplify things, periods are returned (and must be set) in the ISO 8601
standard form C<YYYY-MM>.
=item B<publisher>
Get or set the publisher common to all of the resources in the report.
=item B<platform>
Get or set the platform common to all of the resources in the report.
=back
=head1 CALLBACKS
While processing a report, a number of different B<events> occur. For
example, a B<fixed> event occurs when a field whose value is invalid
is corrected. For event different kind of event, a B<callback> may be
specified that is triggered each time the event occurs; see the B<report>
method for how to specify a callback.
Callbacks must be coderefs, not function or method names.
For example, the following callbacks may be used to provide an indication of
the progress in processing it:
$record_number = 0;
%callbacks = (
'begin_report' => sub {
print STDERR "Beginning report: ";
},
'end_header' => sub {
my ($report, $header) = @_;
print STDERR $report->name, "\n";
}
'end_record' => sub {
my ($report, $record) = @_;
++$record_number;
print STDERR "$record_number "
if $record_number % 20 == 0;
print STDERR "\n"
if $record_number % 200 == 0;
},
'end_report' => sub {
my ($report) = @_;
if ($report->is_valid) {
print STDERR "OK\n";
}
else {
print STDERR "INVALID\n";
}
},
);
By default, the only callback defined is for B<output>; it prints each
line of input (corrected, if there were correctable problems) to
standard output. (Spurious blank lines are not printed.)
Events fall into four broad categories: B<structure>, B<validation>,
B<tracing>, and B<data>.
=head2 Structure
Logically, a COUNTER report has the following structure:
report
header
body
record
record
...
=over 4
=item B<begin_file>(I<$report>, I<$file>)
Parsing of the given file is beginning. This is always the first event
triggered. At the time this callback is invoked, the report has not yet been
identified.
=item B<end_file>(I<$report>, I<$file>)
Parsing of the given file has ended. This is always the last event
triggered.
=item B<begin_report>(I<$report>)
Processing of the report is beginning. At the time this callback is invoked,
( run in 2.259 seconds using v1.01-cache-2.11-cpan-d7f47b0818f )