Astro-SIMBAD-Client
view release on metacpan or search on metacpan
lib/Astro/SIMBAD/Client.pm view on Meta::CPAN
# unpacked from it) but the parity check lets me give a less
# unfriendly error message. CAVEAT: do NOT modify the contents
# of @_, since this will be seen by the caller. Modifying @_
# itself is fine.
sub url_query { ## no critic (RequireArgUnpacking)
@_ % 2 and croak <<eod;
Error - url_query needs an even number of arguments after the query
type.
eod
my ($self, $query, %args) = @_;
### my $debug = $self->get ('debug');
my $dflt = $self->get ('url_args');
foreach my $key (keys %$dflt) {
exists ($args{$key}) or $args{$key} = $dflt->{$key};
}
unless ($args{'output.format'}) {
my $type = $self->get ('type');
$args{'output.format'} = $type_map{$type} || $type;
}
my $resp = $self->_retrieve( "simbad/sim-$query", \%args );
my $rslt = $resp->content();
HAVE_DOUBLE_ENCODED
and $rslt = XML::DoubleEncodedEntities::decode( $rslt );
my $parser;
if (my $type = $type_unmap{$args{'output.format'}}) {
$parser = $self->_get_parser ($type);
return wantarray ? ($parser->($rslt)) : [$parser->($rslt)]
if $parser;
}
return $rslt;
}
} # End local symbol block.
########################################################################
#
# Utility routines
#
# __build_url
#
# Builds a URL based on the currently-set scheme and server, and
# the fragment provided as an argument. If the fragment is an
# HTTP::Request object it is simply returned.
sub __build_url {
my ( $self, $fragment ) = @_;
defined $fragment
or $fragment = '';
eval { $fragment->isa( 'HTTP::Request' ) }
and return $fragment;
$fragment =~ s< \A / ><>smx; # Defensive programming
return sprintf '%s://%s/%s', $self->get( 'scheme' ),
$self->get( 'server' ), $fragment;
}
# _callers_caller();
#
# Returns the name of the subroutine that called the caller.
# Results undefined if not called from a subroutine nested at
# least two deep.
sub _callers_caller {
my $inx = 1;
my $caller;
foreach ( 1 .. 2 ) {
do {
$caller = ( caller $inx++ )[3]
} while '(eval)' eq $caller;
}
return $caller;
}
# $self->_delay
#
# Delays the desired amount of time before issuing the next
# query.
{
my %last;
sub _delay {
my $self = shift;
my $last = $last{$self->{server}} ||= 0;
if ((my $delay = $last + $self->{delay} - time) > 0) {
sleep ($delay);
}
return ($last{$self->{server}} = time);
}
}
# $self->_deprecation_notice( $type, $name );
#
# This method centralizes deprecation. Type is 'attribute' or
# 'method'. Deprecation is driven of the %deprecate hash. Values
# are:
# false - no warning
# 1 - warn on first use
# 2 - warn on each use
# 3 - die on each use.
#
# $self->_deprecation_in_progress( $type, $name )
#
# This method returns true if the deprecation is in progress. In
# practice this means the %deprecate value is defined.
# This is currently unused and commented out
{
my %deprecate = (
method => {
query => 2,
},
);
sub _deprecation_notice {
my ( undef, $type, $name, $repl ) = @_; # Invocant unused
$deprecate{$type} or return;
lib/Astro/SIMBAD/Client.pm view on Meta::CPAN
# $self->can($name) is true, in which case the package is
# ref($self).
#
# If called in scalar context, the package is returned.
sub _parse_subroutine_name {
my ($self, $parser) = @_;
my @parts = split '::', $parser;
my $code = pop @parts;
my $pkg = join '::', @parts;
unless ($pkg) {
my %tried = (__PACKAGE__, 1);
my $inx = 1;
while ($pkg = (caller ($inx++))[0]) {
next if $tried{$pkg};
$tried{$pkg} = 1;
last if $pkg->can ($code);
}
$pkg = ref $self if !$pkg && $self->can ($code);
defined $pkg or croak <<eod;
Error - '$parser' yields undefined package name.
eod
@parts = split '::', $pkg;
}
return wantarray ? ($pkg, $code) : $pkg;
}
# my $resp = $self->_retrieve( $fragment, \%args );
#
# Build a URL from the contents of the 'scheme' and 'server'
# attributes, and the given fragment, and retrieve the data from
# that URL. The \%args argument is optional.
#
# The return is an HTTP::Response object. If the response is
# indicates that the request is unsuccessful we croak with the URL
# (if that can be retrieved) and the status line.
#
# The details depend on the arguments and the state of the
# invocant as follows:
#
# If $url is an HTTP::Request object, it is executed and the
# response returned. Otherwise
#
# If \%args is present and not empty, and the 'post' attribute is
# true, an HTTP post() request is done to the URL, sending the
# data. Otherwise
#
# If there are arguments they are appended to the URL, and an HTTP
# get() is done to the URL.
sub _retrieve {
my ($self, $fragment, $args) = @_;
my $url = $self->__build_url( $fragment );
$args ||= {};
my $debug = $self->get ('debug');
my $ua = _get_user_agent ();
$self->_delay ();
my $resp;
if (eval {$url->isa('HTTP::Request')}) {
$debug
and print 'Debug ', _callers_caller(), 'executing ',
$url->as_string, "\n";
$resp = $ua->request ($url);
} elsif ($self->get ('post') && %$args) {
if ($debug) {
print 'Debug ', _callers_caller(), " posting to $url\n";
foreach my $key (sort keys %$args) {
print " $key => $args->{$key}\n";
}
}
$resp = $ua->post ($url, $args);
} else {
my $join = '?';
foreach my $key (sort keys %$args) {
$url .= $join . _escape_uri( $key ) . '=' . _escape_uri (
$args->{$key} );
$join = '&';
}
$debug
and print 'Debug ', _callers_caller(), " getting from $url\n";
$resp = $ua->get( $url );
}
$debug
and print 'Debug - request: ', $resp->request()->as_string(), "\n";
$resp->is_success()
and return $resp;
my $rq = $resp->request()
or croak $resp->status_line();
my $u = $rq->uri();
croak "$u: ", $resp->status_line();
}
1;
__END__
=back
=head2 Attributes
The Astro::SIMBAD::Client attributes are documented below. The type of
the attribute is given after the attribute name, in parentheses. The
types are:
boolean - a true/false value (in the Perl sense);
hash - a reference to one or more key/value pairs;
integer - an integer;
string - any characters.
Hash values may be specified either as hash references or as strings.
When a hash value is set, the given value updates the hash rather than
replacing it. For example, specifying
$simbad->set (format => {txt => '%MAIN_ID\n'});
does not affect the value of the vo format. If a key is set to the
null value, it deletes the key. All keys in the hash can be deleted
by setting key 'clear' to any true value.
When specifying a string for a hash-valued attribute, it must be of
the form 'key=value'. For example,
$simbad->set (format => 'txt=%MAIN_ID\n');
does the same thing as the previous example. Specifying the key name
without an = sign deletes the key (e.g. set (format => 'txt')).
The Astro::SIMBAD::Client class has the following attributes:
=over
=item autoload
This Boolean attribute determines whether setting the parser should
attempt to autoload its package.
The default is 1 (i.e. true).
( run in 1.108 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )