File Coverage

blib/lib/App/Kramerius/To/Images.pm
Criterion Covered Total %
statement 53 154 34.4
branch 3 52 5.7
condition 0 9 0.0
subroutine 15 19 78.9
pod 2 2 100.0
total 73 236 30.9


line stmt bran cond sub pod time code
1             package App::Kramerius::To::Images;
2              
3 3     3   84957 use strict;
  3         19  
  3         92  
4 3     3   19 use warnings;
  3         6  
  3         79  
5              
6 3     3   1559 use App::Kramerius::V4;
  3         292608  
  3         125  
7 3     3   35 use Class::Utils qw(set_params);
  3         8  
  3         199  
8 3     3   20 use Data::Kramerius;
  3         8  
  3         63  
9 3     3   16 use English;
  3         8  
  3         27  
10 3     3   1722 use Error::Pure qw(err);
  3         12  
  3         148  
11 3     3   18 use Getopt::Std;
  3         8  
  3         145  
12 3     3   19 use HTTP::Request;
  3         7  
  3         144  
13 3     3   24 use IO::Barf qw(barf);
  3         8  
  3         131  
14 3     3   17 use JSON::XS;
  3         8  
  3         191  
15 3     3   22 use LWP::UserAgent;
  3         5  
  3         80  
16 3     3   1791 use METS::Files;
  3         35388  
  3         124  
17 3     3   1821 use Perl6::Slurp qw(slurp);
  3         4777  
  3         19  
18              
19             our $VERSION = 0.03;
20              
21             # Constructor.
22             sub new {
23 2     2 1 649 my ($class, @params) = @_;
24              
25             # Create object.
26 2         7 my $self = bless {}, $class;
27              
28             # LWP::UserAgent object.
29 2         8 $self->{'lwp_user_agent'} = undef;
30              
31             # Process parameters.
32 2         11 set_params($self, @params);
33              
34 2         32 $self->{'_kramerius'} = Data::Kramerius->new;
35              
36 2 100       3288 if (defined $self->{'lwp_user_agent'}) {
37 1 50       13 if (! $self->{'lwp_user_agent'}->isa('LWP::UserAgent')) {
38 1         6 err "Parameter 'lwp_user_agent' must be a LWP::UserAgent instance.";
39             }
40             } else {
41 1         10 $self->{'lwp_user_agent'} = LWP::UserAgent->new;
42 1         3104 $self->{'lwp_user_agent'}->agent('kramerius2images/'.$VERSION);
43             }
44              
45             # Object.
46 1         71 return $self;
47             }
48              
49             # Run.
50             sub run {
51 0     0 1   my $self = shift;
52              
53             # Process arguments.
54 0           $self->{'_opts'} = {
55             'h' => 0,
56             'q' => 0,
57             'v' => 0,
58             };
59 0 0 0       if (! getopts('hqv', $self->{'_opts'}) || (! -r 'ROOT' && @ARGV < 2)
      0        
      0        
60             || $self->{'_opts'}->{'h'}) {
61              
62 0           print STDERR "Usage: $0 [-h] [-q] [-v] [--version] [kramerius_id object_id]\n";
63 0           print STDERR "\t-h\t\tHelp.\n";
64 0           print STDERR "\t-q\t\tQuiet mode.\n";
65 0           print STDERR "\t-v\t\tVerbose mode.\n";
66 0           print STDERR "\t--version\tPrint version.\n";
67 0           print STDERR "\tkramerius_id\tKramerius system id. e.g. ".
68             "mzk\n";
69 0           print STDERR "\tobject_id\tKramerius object id (could be ".
70             "page, series or book edition).\n";
71 0           return 1;
72             }
73 0           my ($kramerius_id, $object_id);
74 0 0         if (@ARGV > 1) {
    0          
75 0           $kramerius_id = shift @ARGV;
76 0           $object_id = shift @ARGV;
77             } elsif (-r 'ROOT') {
78 0           ($kramerius_id, $object_id) = slurp('ROOT', { chomp => 1 });
79             } else {
80 0           err 'Cannot read library id and work id.';
81             }
82              
83 0           $self->{'_kramerius_obj'} = $self->{'_kramerius'}->get($kramerius_id);
84 0 0         if (! defined $self->{'_kramerius_obj'}) {
85 0           err "Library with ID '$kramerius_id' is unknown.";
86             }
87 0           barf('ROOT', <<"END");
88             $kramerius_id
89             $object_id
90             END
91              
92 0           my $quiet = '-q ';
93 0 0         if ($self->{'_opts'}->{'v'}) {
94 0           $quiet = '';
95             }
96              
97 0           my @pages;
98 0 0         if ($self->{'_kramerius_obj'}->version == 3) {
    0          
99              
100             # URI for METS.
101 0           my $mets_uri = $self->{'_kramerius_obj'}->url.'kramerius/mets/'.$kramerius_id.
102             '/'.$object_id;
103              
104             # Get METS.
105 0 0         if ($self->{'_opts'}->{'v'}) {
106 0           print "Downloads $mets_uri\n";
107             }
108 0           my $req = HTTP::Request->new('GET' => $mets_uri);
109 0           my $res = $self->{'lwp_user_agent'}->request($req);
110 0           my $mets;
111 0 0         if ($res->is_success) {
112 0           $mets = $res->content;
113              
114             # Get images from METS file.
115 0           my $obj = METS::Files->new(
116             'mets_data' => $mets,
117             );
118              
119             # Get 'img' files.
120 0           my @page_uris = $obj->get_use_files('img');
121              
122 0 0         if (! @page_uris) {
123 0           err 'No images to download.';
124             }
125              
126             # Get images.
127 0           foreach my $page (@page_uris) {
128 0           my $uri = URI->new($page);
129 0           my @path_segments = $uri->path_segments;
130 0 0         if (! -r $path_segments[-1]) {
131 0 0         if (! $self->{'_opts'}->{'q'}) {
132 0           print "$page\n";
133             }
134 0           $self->_download($page, $path_segments[-1]);
135             }
136              
137             # Strip URI part.
138 0           push @pages, $path_segments[-1];
139             }
140              
141             # Direct file.
142             } else {
143              
144             # TODO Stahnout primo soubor. Udelat na to skript.
145 0           err "Cannot get '$mets_uri' URI.",
146             'HTTP code', $res->code,
147             'Message', $res->message;
148             }
149              
150             } elsif ($self->{'_kramerius_obj'}->version == 4) {
151              
152             # URI for children JSON.
153 0           my $json_uri = $self->{'_kramerius_obj'}->url.'search/api/v5.0/item/uuid:'.
154             $object_id.'/children';
155              
156             # Get JSON.
157 0           my $req = HTTP::Request->new('GET' => $json_uri);
158 0           my $res = $self->{'lwp_user_agent'}->request($req);
159 0           my $json;
160 0 0         if ($res->is_success) {
161 0           $json = $res->content;
162 0           barf($object_id.'.json', $json);
163             } else {
164 0           err "Cannot get '$json_uri' URI.",
165             'HTTP code', $res->code,
166             'message', $res->message;
167             }
168              
169             # Check JSON content type.
170 0 0         if ($res->headers->content_type ne 'application/json') {
171 0           err "Content type isn't 'application/json' for '$json_uri' URI.",
172             'Content-Type', $res->headers->content_type;
173             }
174              
175             # Get perl structure.
176 0           my $json_ar = eval {
177 0           JSON::XS->new->decode($json);
178             };
179 0 0         if ($EVAL_ERROR) {
180 0           err "Cannot parse JSON on '$json_uri' URI.",
181             'JSON decode error', $EVAL_ERROR;
182             }
183              
184             # Each page.
185 0           my $images = 0;
186 0           foreach my $page_hr (@{$json_ar}) {
  0            
187 0 0         if ($page_hr->{'model'} ne 'page') {
188 0           next;
189             }
190 0           my $title = $self->_get_page_title($page_hr);
191 0           my $pid = $page_hr->{'pid'};
192 0           $pid =~ s/^uuid://ms;
193             # TODO Support for page number in $pid =~ uuid:__uuid__@__page_number__ (PDF and number of page in PDF)
194 0 0         if (! $self->{'_opts'}->{'q'}) {
195 0           print "$pid: $title\n";
196             }
197             # XXX Support of jpg only
198 0 0         if (! -r $pid.'.jpg') {
199 0           $self->_do_command("kramerius4 $quiet $kramerius_id $pid");
200             }
201 0           push @pages, $pid.'.jpg';
202 0           $images++;
203             }
204              
205             # One page.
206 0 0         if ($images == 0) {
207 0           my $pid = $object_id;
208 0 0         if (! $self->{'_opts'}->{'q'}) {
209 0           print "$pid: ?\n";
210             }
211             # XXX Support of jpg only
212 0           my $output_file = $pid.'.jpg';
213 0 0         if (! -r $output_file) {
214 0           $self->_do_command("kramerius4 $quiet $kramerius_id $pid");
215             }
216 0           push @pages, $output_file;
217             }
218             } else {
219             err 'Bad version of Kramerius.',
220 0           'Kramerius version', $self->{'_kramerius_obj'}->version;
221             }
222 0           barf('LIST', join "\n", @pages);
223              
224 0           return 0;
225             }
226              
227             sub _download {
228 0     0     my ($self, $uri, $local_file) = @_;
229              
230 0           $self->{'lwp_user_agent'}->get($uri,
231             ':content_file' => $local_file,
232             );
233              
234 0           return;
235             }
236              
237             # Get title from page.
238             sub _get_page_title {
239 0     0     my ($self, $page_hr) = @_;
240              
241 0           my $title;
242 0 0         if (ref $page_hr->{'title'} eq 'ARRAY') {
    0          
243 0           $title = $page_hr->{'title'}->[0];
244             } elsif (ref $page_hr->{'title'} eq '') {
245 0           $title = $page_hr->{'title'};
246             } else {
247 0           err "Cannot get title for page '$page_hr->{'pid'}.'.";
248             }
249 0           $title =~ s/\s+/_/msg;
250              
251 0           return $title;
252             }
253              
254             sub _do_command {
255 0     0     my ($self, $command) = @_;
256              
257 0 0         if ($self->{'_opts'}->{'v'}) {
258 0           print $command."\n";
259             }
260              
261 0           system $command;
262             }
263              
264             1;
265              
266             =pod
267              
268             =encoding utf8
269              
270             =head1 NAME
271              
272             App::Kramerius::To::Images - Base class for kramerius2images script.
273              
274             =head1 SYNOPSIS
275              
276             use App::Kramerius::To::Images;
277              
278             my $app = App::Kramerius::To::Images->new;
279             my $exit_code = $app->run;
280              
281             =head1 METHODS
282              
283             =head2 C<new>
284              
285             my $app = App::Kramerius::To::Images->new;
286              
287             Constructor.
288              
289             Returns instance of object.
290              
291             =head2 C<run>
292              
293             my $exit_code = $app->run;
294              
295             Run.
296              
297             Returns 1 for error, 0 for success.
298              
299             =head1 ERRORS
300              
301             new():
302             From Class::Utils::set_params():
303             Unknown parameter '%s'.
304             Parameter 'lwp_user_agent' must be a LWP::UserAgent instance.
305              
306             run():
307             Bad version of Kramerius.
308             Kramerius version: %s
309             Cannot get title for page '%s'.
310             Cannot get '%s' URI.
311             HTTP code: %s
312             message: %s
313             Cannot parse JSON on '%s' URI.
314             JSON decode error: %s
315             Cannot read library id and work id.
316             Content type isn't 'application/json' for '%s' URI.
317             Content-Type: %s
318             Library with ID '%s' is unknown.
319             No images to download.
320              
321             =head1 EXAMPLE
322              
323             use strict;
324             use warnings;
325              
326             use App::Kramerius::To::Images;
327              
328             # Arguments.
329             @ARGV = (
330             '-h',
331             );
332              
333             # Run.
334             exit App::Kramerius::To::Images->new->run;
335              
336             # Output like:
337             # Usage: ./ex1.pl [-h] [-q] [-v] [--version] [kramerius_id object_id]
338             # -h Help.
339             # -q Quiet mode.
340             # -v Verbose mode.
341             # --version Print version.
342             # kramerius_id Kramerius system id. e.g. mzk
343             # object_id Kramerius object id (could be page, series or book edition).
344              
345             =head1 DEPENDENCIES
346              
347             L<App::Kramerius::V4>,
348             L<Class::Utils>,
349             L<Data::Kramerius>,
350             L<English>,
351             L<Error::Pure>,
352             L<Getopt::Std>,
353             L<HTTP::Request>,
354             L<IO::Barf>,
355             L<JSON::XS>,
356             L<LWP::UserAgent>,
357             L<METS::Files>,
358             L<Perl6::Slurp>.
359              
360             =head1 REPOSITORY
361              
362             L<https://github.com/michal-josef-spacek/App-Kramerius-To-Images>
363              
364             =head1 AUTHOR
365              
366             Michal Josef Špaček L<mailto:skim@cpan.org>
367              
368             L<http://skim.cz>
369              
370             =head1 LICENSE AND COPYRIGHT
371              
372             © 2021 Michal Josef Špaček
373              
374             BSD 2-Clause License
375              
376             =head1 VERSION
377              
378             0.03
379              
380             =cut