File Coverage

blib/lib/App/MARC/List.pm
Criterion Covered Total %
statement 113 123 91.8
branch 26 34 76.4
condition 15 15 100.0
subroutine 15 15 100.0
pod 2 2 100.0
total 171 189 90.4


line stmt bran cond sub pod time code
1             package App::MARC::List;
2              
3 4     4   177903 use strict;
  4         11  
  4         147  
4 4     4   37 use warnings;
  4         7  
  4         262  
5              
6 4     4   2383 use Class::Utils qw(set_params);
  4         69109  
  4         100  
7 4     4   427 use English;
  4         8  
  4         25  
8 4     4   2388 use Error::Pure qw(err);
  4         23  
  4         280  
9 4     4   4935 use Getopt::Std;
  4         10712  
  4         349  
10 4     4   2954 use IO::Uncompress::AnyUncompress qw($AnyUncompressError);
  4         411350  
  4         642  
11 4     4   2808 use List::MoreUtils qw(uniq);
  4         86596  
  4         40  
12 4     4   6335 use List::Util qw(max);
  4         12  
  4         2373  
13 4     4   2486 use MARC::Batch;
  4         6627  
  4         239  
14 4     4   4046 use MARC::File::XML (BinaryEncoding => 'utf8', RecordFormat => 'MARC21');
  4         679412  
  4         38  
15 4     4   2013 use Unicode::UTF8 qw(decode_utf8 encode_utf8);
  4         2579  
  4         4789  
16              
17             our $VERSION = 0.09;
18              
19             # Constructor.
20             sub new {
21 15     15 1 786441 my ($class, @params) = @_;
22              
23             # Create object.
24 15         44 my $self = bless {}, $class;
25              
26             # Process parameters.
27 15         83 set_params($self, @params);
28              
29             # Object.
30 14         741 return $self;
31             }
32              
33             # Run.
34             sub run {
35 13     13 1 36 my $self = shift;
36              
37             # Process arguments.
38 13         90 $self->{'_opts'} = {
39             'f' => 0,
40             'h' => 0,
41             's' => 0,
42             };
43 13 100 100     56 if (! getopts('fhs', $self->{'_opts'})
      100        
44             || $self->{'_opts'}->{'h'}
45             || @ARGV < 2) {
46              
47 4         407 print STDERR "Usage: $0 [-f] [-h] [-s] [--version] marc_xml_file field [subfield]\n";
48 4         81 print STDERR "\t-f\t\tPrint frequency.\n";
49 4         38 print STDERR "\t-h\t\tPrint help.\n";
50 4         30 print STDERR "\t-s\t\tSkip controls of field/subfield.\n";
51 4         29 print STDERR "\t--version\tPrint version.\n";
52 4         29 print STDERR "\tmarc_xml_file\tMARC XML file, could be compressed.\n";
53 4         59 print STDERR "\tfield\t\tMARC field (field number or 'leader' string).\n";
54 4         41 print STDERR "\tsubfield\tMARC subfield (for datafields).\n";
55 4         22 return 1;
56             }
57 9         380 my $marc_xml_file = shift @ARGV;
58 9         21 my $marc_field = shift @ARGV;
59 9         22 my $marc_subfield = shift @ARGV;
60              
61 9 50       33 if (! $self->{'_opts'}->{'s'}) {
62 9 100 100     68 if ($marc_field ne 'leader'
63             && $marc_field !~ m/^\d+$/ms) {
64              
65 1         7 err "Bad field definition. Must be a 'leader' or numeric value of the field.";
66             }
67              
68 8 100 100     84 if ($marc_field ne 'leader'
      100        
69             && int($marc_field) > 9
70             && ! defined $marc_subfield) {
71              
72 1         6 err 'Subfield is required.';
73             }
74             }
75              
76 7 100       273 if (! -r $marc_xml_file) {
77 1         11 err "File '$marc_xml_file' doesn't exist.";
78             }
79 6         17 my ($fh, $errno);
80 6 50       29 if ($self->_open_marc_input($marc_xml_file, \$fh, \$errno)) {
81 0         0 print STDERR "Cannot open file '$marc_xml_file'.";
82 0 0       0 if (defined $errno) {
83 0         0 print STDERR "\tErrno: $errno\n";
84             }
85 0         0 return 1;
86             }
87 6         12 my $marc_batch = eval {
88 6         55 MARC::Batch->new('XML', $fh);
89             };
90 6 50       1286 if ($EVAL_ERROR) {
91 0         0 print STDERR "Cannot open MARC XML stream.\n";
92 0         0 print STDERR "\tError: $EVAL_ERROR\n";
93 0         0 return 1;
94             }
95 6         13 my $ret_hr = {};
96 6         9 my $num = 1;
97 6         12 my $previous_record;
98 6         8 while (1) {
99 18         35 my $record = eval {
100 18         68 $marc_batch->next;
101             };
102 18 100       58849 if ($EVAL_ERROR) {
103 1 50       75 print STDERR "Cannot process '$num' record. ".
104             (
105             defined $previous_record
106             ? "Previous record is ".encode_utf8($previous_record->title)."\n"
107             : ''
108             );
109 1         38 print STDERR "Error: $EVAL_ERROR\n";
110 1         4 next;
111             }
112 17 100       51 if (! defined $record) {
113 6         16 last;
114             }
115 11         181 $previous_record = $record;
116              
117 11 100       39 if ($marc_field eq 'leader') {
118 4         14 my $leader = $record->leader;
119 4         46 $ret_hr->{"'".$leader."'"}++;
120             } else {
121 7         27 my @fields = $record->field($marc_field);
122 7         1771 foreach my $field (@fields) {
123 7 100       23 if (defined $marc_subfield) {
124 6         25 my @subfield_values = $field->subfield($marc_subfield);
125 6         214 foreach my $subfield_value (@subfield_values) {
126 6         29 $ret_hr->{$subfield_value}++;
127             }
128             } else {
129 1         6 my $data = $field->data;
130 1         19 $ret_hr->{$data}++;
131             }
132             }
133             }
134 11         22 $num++;
135             }
136              
137             # Print out.
138 6 100       10 if (%{$ret_hr}) {
  6         19  
139 5 100       22 if ($self->{'_opts'}->{'f'}) {
140 2         4 my $max = max(values %{$ret_hr});
  2         12  
141 2         7 my $num = length($max);
142             print join "\n",
143 4         162 map { sprintf("%${num}s", $ret_hr->{$_}).' '.encode_utf8($_) }
144             reverse sort {
145 3 50       17 $ret_hr->{$a} <=> $ret_hr->{$b}
146             ||
147             $b cmp $a
148             }
149 2         4 keys %{$ret_hr};
  2         12  
150             } else {
151 3         7 print join "\n", map { encode_utf8($_) } sort keys %{$ret_hr};
  3         257  
  3         16  
152             }
153 5         179 print "\n";
154             }
155            
156 6         270 return 0;
157             }
158              
159             sub _open_marc_input {
160 6     6   19 my ($self, $path, $fh_sr, $errno_sr) = @_;
161              
162             # Compression autodetection.
163 6         64 ${$fh_sr} = IO::Uncompress::AnyUncompress->new($path);
  6         13047  
164 6 50       17 if (defined ${$fh_sr}) {
  6         19  
165 6         36 return 0;
166             }
167 0           ${$errno_sr} = $AnyUncompressError;
  0            
168              
169 0           return 1;
170             }
171              
172             1;
173              
174              
175             __END__