File Coverage

blib/lib/WebService/Audioscrobbler/DataFetcher.pm
Criterion Covered Total %
statement 18 44 40.9
branch 0 14 0.0
condition n/a
subroutine 6 11 54.5
pod n/a
total 24 69 34.7


line stmt bran cond sub pod time code
1             package WebService::Audioscrobbler::DataFetcher;
2 1     1   5 use warnings;
  1         1  
  1         23  
3 1     1   5 use strict;
  1         2  
  1         21  
4 1     1   4 use CLASS;
  1         2  
  1         4  
5 1     1   28 use base 'Class::Accessor::Fast';
  1         1  
  1         55  
6            
7 1     1   887 use Cache::FileCache;
  1         60865  
  1         43  
8 1     1   12 use URI;
  1         3  
  1         8  
9            
10             require LWP::Simple;
11             require XML::Simple;
12            
13             =head1 NAME
14            
15             WebService::Audioscrobbler::DataFetcher - Cached data fetching provider
16            
17             =cut
18            
19             our $VERSION = '0.07';
20            
21             # object accessors
22             CLASS->mk_accessors(qw/base_url cache_root cache/);
23            
24             =head1 SYNOPSIS
25            
26             This is responsible for fetching and caching all data requested from Audioscrobbler
27             WebServices, as recommended by their usage policy.
28            
29             It can actually function as a generic XML-fetcher-and-converter-to-hashrefs and has
30             no limitations regarding being used only for Audioscrobbler WebServices. In the future,
31             it might even became a completely separate module.
32            
33             use WebService::Audioscrobbler::DataFetcher;
34            
35             my $data_fetcher = WebService::Audioscrobbler::DataFetcher->new(
36             "http://www.my-base-url.com/base_dir/"
37             );
38            
39             # retrieves "http://www.my-base-url.com/base_dir/myown/resource.xml"
40             # and parses it through XML::Simple::XMLin so we get a hashref
41             my $data = $data_fetcher->fetch("myown/resource.xml")
42            
43             =cut
44            
45             =head1 FIELDS
46            
47             =head2 C
48            
49             This is the base URL from where data will be fetched.
50            
51             =head2 C
52            
53             This is the underlying cache object. By default, this will be a
54             L object.
55            
56             =head2 C
57            
58             This is the root directory where the cache will be created. It should only be
59             set as a parameter to C, setting it afterwards won't have any effect.
60            
61             =cut
62            
63             =head1 METHODS
64            
65             =cut
66            
67             =head2 C
68            
69             =head2 C
70            
71             Creates a new object using either the given C<$base_url> or the C<\%fields>
72             hashref. Any of the above fields can be specified. If the C field is
73             undefined, C will be called after object construction.
74            
75             =cut
76            
77             sub new {
78 0     0     my $class = shift;
79 0           my $base_or_params = shift;
80            
81 0 0         my $self = $class->SUPER::new(
82             ref $base_or_params eq 'HASH' ? $base_or_params : { base_url => $base_or_params }
83             );
84            
85             # base_url is mandatory
86 0 0         $self->croak("base_url not set")
87             unless defined $self->base_url;
88            
89             # guarantee it's an URI object
90 0 0         $self->base_url(URI->new($self->base_url))
91             unless $self->base_url->isa('URI');
92            
93             # crate a new cache object, unless we're already given one
94 0 0         $self->create_cache unless $self->cache;
95            
96 0           return $self;
97             }
98            
99             =head2 C
100            
101             Creates a new L object and saves it in the C field.
102             The cache has a daily auto purging turned on and data will expire by default
103             in 3 days, which is reasonable since most of Audioscrobbler data changes at
104             most weekly. The cache root will be as specified by the C field
105             (if it's undefined, L defaults will be used).
106            
107             =cut
108            
109             sub create_cache {
110 0     0     my $self = shift;
111 0           $self->cache(
112             Cache::FileCache->new( {
113             auto_purge_on_set => 1,
114             auto_purge_interval => 86400, # 1 day
115             default_expires_in => 259200, # 3 days
116             cache_root => $self->cache_root
117             } )
118             )
119             }
120            
121             =head2 C
122            
123             Actually fetches a XML resource URL. If the resource is not already cached,
124             C is called it's results are then cached. The results are then
125             processed by C so we end up with a nice hashref as our
126             return value.
127            
128             =cut
129            
130             sub fetch {
131 0     0     my ($self, $resource) = @_;
132            
133             # build and normalize the URL
134 0           my $uri = $self->base_url->clone;
135 0           $uri->path_segments(grep {length} $uri->path_segments, split '/', $resource);
  0            
136            
137             # try to fetch a cached copy of the data
138 0           my $data = $self->cache->get($uri);
139            
140             # not in cache
141 0 0         unless (defined $data) {
142 0           my $resp = $self->retrieve_data($uri);
143            
144             # parse it into a hashref
145 0           $data = XML::Simple::XMLin($resp);
146            
147             # cache it for future references
148 0           $self->cache->set($uri, $data);
149             }
150            
151 0           return $data;
152            
153             }
154            
155             =head2 C
156            
157             Retrieves data from the specified $uri using L and returns it.
158            
159             =cut
160            
161             sub retrieve_data {
162 0     0     my ($self, $uri) = @_;
163            
164             # warn "\nRetrieving data from $uri...\n";
165            
166 0 0         my $resp = LWP::Simple::get($uri)
167             or $self->croak("Error while fetching data from '$uri'");
168            
169 0           utf8::upgrade($resp);
170            
171 0           return $resp;
172             }
173            
174             =head2 C
175            
176             Shortcut for C which can be called as a method.
177            
178             =cut
179            
180             sub croak {
181 0 0   0     shift if $_[0]->isa(CLASS);
182 0           require Carp;
183 0           Carp::croak(@_);
184             }
185            
186             =head1 AUTHOR
187            
188             Nilson Santos Figueiredo Júnior, C<< >>
189            
190             =head1 COPYRIGHT & LICENSE
191            
192             Copyright 2006-2007 Nilson Santos Figueiredo Júnior, all rights reserved.
193            
194             This program is free software; you can redistribute it and/or modify it
195             under the same terms as Perl itself.
196            
197             =cut
198            
199             1; # End of WebService::Audioscrobbler::DataFetcher