Biblio-Refbase
view release on metacpan or search on metacpan
lib/Biblio/Refbase.pm view on Meta::CPAN
}
$self->{format};
}
sub style {
my $self = shift;
if (@_) {
my $style = shift;
_check_style($style);
$self->{style} = $style;
return $self;
}
$self->{style};
}
sub order {
shift->_accessor('order', @_);
}
sub rows {
shift->_accessor('rows', @_);
}
sub records {
shift->_accessor('records', @_);
}
sub ua {
my $self = shift;
if (@_) {
my $ua = shift;
croak q{Accessor 'ua' requires an object based on 'LWP::UserAgent'}
unless ref $ua and $ua->isa('LWP::UserAgent');
$self->{ua} = $ua;
return $self;
}
$self->{ua};
}
#
# public instance methods
#
sub search {
my $self = shift;
my %args = @_;
my $account = $self->_account_args(\%args);
my $search = $self->_search_args(\%args);
if (%args) {
croak q{Unknown arguments provided to 'search' method:}
. join("\n ", '', sort keys %args) . "\n";
}
return $self->_search($account, $search);
}
sub upload {
my $self = shift;
unshift @_, 'content' if @_ % 2;
my %args = @_;
my $account = $self->_account_args(\%args);
my $upload = $self->_upload_args(\%args);
my $show = delete $args{show};
$show = %args unless defined $show;
my $search = $self->_search_args(\%args);
if (%args) {
croak q{Unknown arguments provided to 'upload' method:}
. join("\n ", '', sort keys %args) . "\n";
}
my $url = $account->{url} . REFBASE_IMPORT;
my $request = $upload->{uploadFile}
? POST $url, Content_Type => 'form-data', Content => $upload
: POST $url, $upload;
my $response = $self->_request($account, $request);
unless ($response->is_error) {
if (defined(my $location = $response->header('location'))) {
if ($location =~ /^(${\REFBASE_SHOW}\?)/o) {
my $q = URI->new($location)->query_form_hash;
my ($rows) = ($q->{headerMsg} || '') =~ /(\d+)/;
my $records = $q->{records} || '';
if ($show) {
$search->{records} ||= $q->{records};
$search->{rows} ||= $rows;
$response = $self->_search($account, $search);
}
else {
my $content = $q->{headerMsg} ? $q->{headerMsg} . ' ' : '';
$content .= $q->{records} if $q->{records};
$response->code(HTTP_OK);
$response->message('');
$response->content($content);
}
$response->records($records)->rows($rows);
}
else {
$response->code(HTTP_NOT_IMPLEMENTED);
$response->message('Unexpected redirect location');
}
}
elsif (index(${$response->content_ref}, scalar REFBASE_MSG_FORBIDDEN) == 0) {
$response->code(HTTP_FORBIDDEN);
$response->message('');
}
else {
$response->code(HTTP_NOT_IMPLEMENTED);
$response->message('Unexpected response');
}
}
return $response
}
sub ping {
my $self = shift;
unshift @_, 'url' if @_ % 2;
# use 'simple_request' instead of 'head' so redirections won't be followed
# thus a redirection (e.g. to error page) will fail, too
return $self->ua->simple_request(
HEAD $self->_account_args({ @_ })->{url}
)->is_success;
}
#
# public static methods
#
sub formats {
return sort +REFBASE_CITATION_FORMATS, REFBASE_EXPORT_FORMATS;
}
lib/Biblio/Refbase.pm view on Meta::CPAN
password => delete $args->{password} || $self->password || REFBASE_DEFAULT_PASSWORD,
relogin => $relogin,
};
}
# mapping of module's argument names to refbase names
my %_names = (
records => 'records',
order => 'citeOrder',
rows => 'showRows',
start => 'startRecord',
query => 'queryType',
view => 'viewType',
);
# setup search parameters from arguments hash, dynamic and static defaults
sub _search_args {
my ($self, $args) = @_;
my %param;
for (REFBASE_QUERY_PARAMS) {
if (defined(my $value = delete $args->{$_})) {
$param{$_} = $value;
}
}
$param{serial} = '.+' unless %param;
my $format = $self->_format(delete $args->{format});
@param{keys %$format} = values %$format;
if (not exists $args->{style} or defined(my $style = delete $args->{style})) {
if (defined($style = $self->_style($style))) {
$param{citeStyle} = $style;
}
}
for (qw'records order rows') {
if (my $value = delete $args->{$_} || $self->$_) {
$param{$_names{$_}} = $value;
}
}
for (qw'start query view') {
if (my $value = delete $args->{$_}) {
$param{$_names{$_}} = $value;
}
}
if (delete $args->{showquery}) {
$param{showquery} = 1;
}
if (defined(my $showlinks = delete $args->{showLinks})) {
$param{showLinks} = 0 if $showlinks eq '0';
}
$param{client} = $self->{_client};
return \%param;
}
# setup upload parameters from arguments hash, dynamic and static defaults
sub _upload_args {
my ($self, $args) = @_;
my %param;
if (defined(my $content = delete $args->{content})) {
$param{uploadFile} = [ undef, 'filename', Content => $content ];
$param{formType} = 'import';
}
elsif (defined(my $source_ids = delete $args->{source_ids})) {
$param{sourceIDs} = ref $source_ids eq 'ARRAY'
? join ' ', @$source_ids
: $source_ids;
$param{formType} = 'importID';
}
else {
croak q{upload requires either record content supplied by parameter 'content' or }
. q{a list of record IDs in parameter 'source_ids'};
}
if (delete $args->{skipbad}) {
$param{skipBadRecords} = 1;
}
if (defined(my $only = delete $args->{only})) {
$param{importRecords} = $only;
$param{importRecordsRadio} = 'only';
}
$param{client} = $self->{_client};
return \%param;
}
# get the format and style parameters
sub _format {
my ($self, $name) = @_;
return _check_format($name || $self->format || REFBASE_DEFAULT_FORMAT);
}
sub _style {
my ($self, $name) = @_;
return _check_style($name || $self->style);
}
# extension to HTTP::Response
package Biblio::Refbase::Response;
# todo: investigation required on adding a DESTROY method
use base 'HTTP::Response';
sub _accessor {
my $self = shift;
my $field = '_BRR_' . shift;
if (@_) {
$self->{$field} = shift;
return $self;
}
return $self->{$field};
}
sub hits { shift->_accessor('hits', @_) }
sub rows { shift->_accessor('rows', @_) }
sub records { shift->_accessor('records', @_) }
1;
__END__
=head1 NAME
Biblio::Refbase - Perl interface to refbase bibliographic manager
=head1 VERSION
This is Biblio::Refbase version 0.0.2, tested against refbase 0.9.5.
=head1 SYNOPSIS
use Biblio::Refbase;
my $refbase = Biblio::Refbase->new(
url => 'http://beta.refbase.net/',
user => 'guest@refbase.net',
password => 'guest',
);
my $response = $refbase->search(
keywords => 'baltic sea', # Search in keywords.
style => 'Chicago', # Set citation style.
);
if ($response->is_success) { # all methods from
if ($response->hits) { # HTTP::Response
print $response->content; # available
}
else {
print 'Nothing found!';
}
}
else {
print 'An error occurred: ', $response->status_line;
}
print "\n\n";
$response = $refbase->upload(
user => 'user@refbase.net', # Switch user for
password => 'user', # this request.
show => 1, # Return records
format => 'BibTeX', # in BibTeX format.
source_ids => [ # Upload records
'arXiv:cs/0106057', # from arXiv.org
'arXiv:cond-mat/0210361', # via source IDs.
],
);
if ($response->is_success) {
print 'Number of records imported: ', $response->rows , "\n";
print 'ID range of records: ' , $response->records, "\n";
print "Records:\n\n", $response->content;
}
# Upload records by supplying a string of content:
# $response = $refbase->upload( content => $content );
=head1 DESCRIPTION
Biblio::Refbase is an object-oriented interface to refbase
Web Reference Database sites.
refbase (L<http://www.refbase.net/>) is a web-based bibliographic manager
which can import and export references in various formats (including BibTeX,
Endnote, MODS and OpenOffice).
=head1 CONSTRUCTOR
=over 4
=item $refbase = Biblio::Refbase->new(%options);
Creates a new C<Biblio::Refbase> instance and returns it.
Key/value pair arguments set up the initial state. All arguments are
optional and define instance-wide default parameters for the method
calls that follow. With the exception of 'ua' these defaults can
be overridden on demand by method calls.
For missing parameters this module will either fall back to its own
static default values or let the targeted refbase site decide.
These are the default values used by this module:
Key Default Comment
--------------------------------------------------------------
url http://localhost/ base URL of a refbase site
user user@refbase.net
password start
relogin 1 relogin if session gets invalid
format ASCII output format
ua (create new) LWP::UserAgent object for reuse
The other available keys are:
Key Comment
------------------------------------
style citation style
order sort order of records
rows maximum number of records
records selection of record IDs
See L<"ACCESSORS"> section for further description.
Unless the key 'ua' contains an instance of C<LWP::UserAgent>, any additional
entries in the C<%options> hash will be passed unmodified to the constructor
of C<LWP::UserAgent>, which is used for performing the requests.
E.g. you can set your own user agent identification and specify a timeout
this way:
$refbase = Biblio::Refbase->new(
agent => 'My Refbase Client',
timeout => 5,
);
lib/Biblio/Refbase.pm view on Meta::CPAN
=item $response = $refbase->search(%args);
Searches a refbase database.
With the exception of 'ua' each instance-wide configurable value
can also be defined on a per-request basis (and thus will override
any given default).
See L<"ACCESSORS"> section for further description of these arguments:
url relogin order
user format rows
password style records
The following keys correspond to fields in the refbase database:
author Author
title Title
type Type
year Year
publication Publication
abbrev_journal Abbreviated Journal
keywords Keywords
abstract Abstract
thesis Thesis
area Area
notes Notes
location Location
serial Serial (ID)
date Creation date
contribution_id institutional abbreviation
The 'date' key requires a date string in the format 'YYYY-MM-DD'.
The other fields can be searched with MySQL regular expressions.
For further details look at section 'Search syntax'
(L<http://www.refbase.net/index.php/Searching#Search_syntax>)
in the refbase documentation. For an explanation of the database fields
refer to page 'Table refs' (L<http://www.refbase.net/index.php/Table_refs>).
Custom search conditions:
where code for SQL WHERE clause
The content of the 'where' key must be valid MySQL code which refbase
will insert into the WHERE clause of its internally generated SQL query.
Field independent search arguments are:
query combination of searched fields: 'and' (default) or 'or'
start offset of the first search result, starting with 1
Special output options for ASCII and HTML formats:
showquery show SQL statement if set to 1 (ASCII only)
showlinks don't show links column if set to 0 (HTML only)
view view type (HTML only): 'Web', 'Print' or 'Mobile'
Refer to L<"EXAMPLES"> section for a short tutorial and working code
snippets.
=item $response = $refbase->upload(%args);
Imports/uploads records to a refbase database.
As with the C<search> method, all instance-wide configured values can be
overridden on a per-request basis (except 'ua'). See C<search> method and
L<"ACCESSORS"> section.
The C<upload> method requires one of these two keys to be present in the
arguments hash:
content a string containing records in a format known by refbase
source_ids a string or list of record IDs recognized by refbase
The 'source_ids' can be supplied either as a string of IDs separated by
blanks or as a reference to an array. If both keys are present, 'content'
will be used and 'source_ids' will be ignored.
Optional keys are:
skipbad skip unrecognized records if set to a true value
only record numbers/range to be imported from the source
show immediately search for the records imported by this call
if set to a true value
If 'show' is set to a true value or any search field parameters (see
C<search> method) are present, the method call will perform a search request
after importing. The search request will automatically set the record selection
to the new IDs of the freshly imported records (overridable by 'records' key)
and the maximum number of records to the number of records that have
been imported (overridable by 'rows' key). I.e. if 'show' is true and no
search field parameters are set, the C<upload> method will return all
imported records (in the desired/default format and style).
Refer to L<"EXAMPLES"> section for a short tutorial and working code
snippets.
=item $response = $refbase->upload($content, %args);
If the constructor is called with an uneven arguments list the first
element will be taken as 'content'.
=item $boolean = $refbase->ping;
Checks if configured base URL is accessible.
=back
=head1 STATIC METHODS
=over 4
=item @formats = $refbase->formats;
=item @formats = Biblio::Refbase->formats;
Returns a list of available output formats known by this module.
=item @styles = $refbase->styles;
=item @styles = Biblio::Refbase->styles;
Returns a list of available citation styles known by this module.
=back
=head1 RESPONSE ACCESSOR METHODS
The C<search> and C<upload> methods return C<$response> objects.
A C<$response> object is a formerly instance of C<HTTP::Response>
that has been re-blessed into the package C<Biblio::Refbase::Response>.
This package subclasses C<HTTP::Response> and extends it by three fields
and the corresponding accessors. No methods are overridden.
=over 4
=item $response->hits;
Indicates the success of a C<search> request:
1 search has found some records
0 search has found nothing
undef search has failed
=item $response->rows;
Returns the number of records that have been imported by an C<upload>
request.
=item $response->records;
Returns the record ID range of the imported records, i.e. the first ID and the
last ID of the new records (joined by the minus sign). Or a single ID, if only
one record has been imported.
=back
See the documentation of C<HTTP::Response> for the methods inherited from
the base class.
=head1 EXAMPLES
=head2 Searching
First, a very simple example that will just perform a search without
applying any user parameters:
$refbase = Biblio::Refbase->new; # create new instance
$response = $refbase->search; # search with defaults
$content = $response->content; # store content
If there's an unmodified out-of-the-box installation of refbase at localhost,
C<$content> should now contain 5 records in ASCII format.
You should check the status of the C<$response> object before processing the
content. All accessors known from C<HTTP::Response> are available plus
L<the accessors added by this module|"RESPONSE ACCESSOR METHODS">:
if ($response->is_success) {
if ($response->hits) { # hits is special to this module
print "Found something!\n";
$content = $response->content;
}
else {
print "Found nothing!\n";
}
}
else {
print 'An error occurred: ', $response->status_line, "\n";
$http_code = $response->code;
$message = $response->message;
}
Let's provide the C<$refbase> object with connection parameters to access
the official beta refbase site:
$refbase->url('http://beta.refbase.net/');
$refbase->user('guest@refbase.net');
$refbase->password('guest');
If you want you can chain the accessors:
$refbase->url('http://beta.refbase.net/')
->user('guest@refbase.net')
->password('gest');
In the chained accessors example there was an intentional typo:
( run in 0.927 second using v1.01-cache-2.11-cpan-b16cb0d3907 )