File Coverage

blib/lib/PICA/Data.pm
Criterion Covered Total %
statement 25 91 27.4
branch 0 48 0.0
condition 0 9 0.0
subroutine 9 14 64.2
pod n/a
total 34 162 20.9


line stmt bran cond sub pod time code
1             package PICA::Data;
2 4     4   32767 use strict;
  4         11  
  4         125  
3 4     4   24 use warnings;
  4         10  
  4         179  
4              
5             our $VERSION = '0.33';
6              
7 4     4   24 use Exporter 'import';
  4         9  
  4         425  
8             our @EXPORT_OK = qw(pica_parser pica_writer pica_path pica_xml_struct
9             pica_values pica_value pica_fields pica_holdings pica_items);
10             our %EXPORT_TAGS = (all => [@EXPORT_OK]);
11              
12             our $ILN_PATH = PICA::Path->new('101@a');
13             our $EPN_PATH = PICA::Path->new('203@/**0');
14              
15 4     4   26 use Carp qw(croak);
  4         9  
  4         292  
16 4     4   28 use Scalar::Util qw(reftype blessed);
  4         12  
  4         327  
17 4     4   42 use List::Util qw(first);
  4         13  
  4         362  
18 4     4   2372 use IO::Handle;
  4         24378  
  4         265  
19 4     4   1255 use PICA::Path;
  4         16  
  4         2820  
20              
21             sub pica_values {
22 0     0     my ($record, $path) = @_;
23              
24 0 0         $path = eval { PICA::Path->new($path) } unless ref $path;
  0            
25 0 0         return unless ref $path;
26              
27 0           return $path->record_subfields($record);
28             }
29              
30             sub pica_fields {
31 0     0     my ($record, $path) = @_;
32              
33 0 0         $path = eval { PICA::Path->new($path) } unless ref $path;
  0            
34 0 0         return [] unless defined $path;
35              
36 0           return $path->record_fields($record);
37             }
38              
39             sub pica_value {
40 0     0     my ($record, $path) = @_;
41              
42 0 0         $record = $record->{record} if reftype $record eq 'HASH';
43 0 0         $path = eval { PICA::Path->new($path) } unless ref $path;
  0            
44 0 0         return unless defined $path;
45              
46 0           foreach my $field (@$record) {
47 0 0         next unless $path->match_field($field);
48 0           my @values = $path->match_subfields($field);
49 0 0         return $values[0] if @values;
50             }
51              
52 0           return;
53             }
54              
55             sub pica_items {
56 0     0     my ($record) = @_;
57            
58 0           my $blessed = blessed($record);
59 0 0         $record = $record->{record} if reftype $record eq 'HASH';
60 0           my (@items, $current, $occurrence);
61              
62 0           foreach my $field (@$record) {
63 0 0         if ($field->[0] =~ /^2/) {
    0          
64            
65 0 0 0       if ( ($occurrence // '') ne $field->[1] ) {
66 0 0         if ($current) {
67 0           push @items, $current;
68 0           $current = undef;
69             }
70 0           $occurrence = $field->[1];
71             }
72            
73 0   0       $current //= { record => [] };
74              
75 0           push @{$current->{record}}, [ @$field ];
  0            
76 0 0         if ($field->[0] eq '203@') {
77 0           ($current->{_id}) = $EPN_PATH->match_subfields($field);
78             }
79             } elsif ($current) {
80 0           push @items, $current;
81 0           $current = undef;
82 0           $occurrence = undef;
83             }
84             }
85              
86 0 0         push @items, $current if $current;
87              
88 0 0         if ($blessed) {
89 0           bless $_, $blessed for @items;
90             }
91              
92 0           return \@items;
93             }
94              
95             sub pica_holdings {
96 0     0     my ($record) = @_;
97              
98 0           my $blessed = blessed($record);
99 0 0         $record = $record->{record} if reftype $record eq 'HASH';
100 0           my (@holdings, $field_buffer, $iln);
101              
102 0           foreach my $field (@$record) {
103 0           my $tag = substr $field->[0], 0, 1;
104 0 0         if ($tag eq '0') {
    0          
105 0           next;
106             } elsif ($tag eq '1') {
107 0 0         if ($field->[0] eq '101@') {
108 0           my ($id) = $ILN_PATH->match_subfields($field);
109 0 0 0       if ( defined $iln && ($id // '') ne $iln ) {
      0        
110 0           push @holdings, { record => $field_buffer, _id => $iln };
111             }
112 0           $field_buffer = [ [@$field] ];
113 0           $iln = $id;
114 0           next;
115             }
116             }
117 0           push @$field_buffer, [@$field];
118             }
119              
120 0 0         if (@$field_buffer) {
121 0           push @holdings, { record => $field_buffer, _id => $iln };
122             }
123              
124 0 0         if ($blessed) {
125 0           bless $_, $blessed for @holdings;
126             }
127              
128 0           return \@holdings;
129             }
130              
131             *values = *pica_values;
132             *value = *pica_value;
133             *fields = *pica_fields;
134             *holdings = *pica_holdings;
135             *items = *pica_items;
136              
137 4     4   2024 use PICA::Parser::XML;
  0            
  0            
138             use PICA::Parser::Plus;
139             use PICA::Parser::Plain;
140             use PICA::Parser::Binary;
141             use PICA::Writer::XML;
142             use PICA::Writer::Plus;
143             use PICA::Writer::Plain;
144             use PICA::Writer::Binary;
145             use PICA::Writer::PPXML;
146              
147             sub pica_parser {
148             _pica_module('PICA::Parser', @_)
149             }
150              
151             sub pica_writer {
152             _pica_module('PICA::Writer', @_)
153             }
154              
155             sub pica_path {
156             PICA::Path->new(@_)
157             }
158              
159             sub _pica_module {
160             my $base = shift;
161             my $type = lc(shift) // '';
162              
163             if ( $type =~ /^(pica)?plus$/ ) {
164             "${base}::Plus"->new(@_);
165             } elsif ( $type eq 'binary' ) {
166             "${base}::Binary"->new(@_);
167             } elsif ( $type =~ /^(pica)?plain$/ ) {
168             "${base}::Plain"->new(@_);
169             } elsif ( $type =~ /^(pica)?xml$/ ) {
170             "${base}::XML"->new(@_);
171             } elsif ( $type =~ /^(pica)?ppxml$/ ) {
172             "${base}::PPXML"->new(@_);
173             } else {
174             croak "unknown PICA parser type: $type";
175             }
176             }
177              
178             sub write {
179             my $pica = shift;
180             my $writer = $_[0];
181             unless (blessed $writer) {
182             $writer = pica_writer(@_ ? @_ : 'plain');
183             }
184             $writer->write($pica);
185             }
186              
187             sub string {
188             my ($pica, $type, %options) = @_;
189             my $string = "";
190             $type ||= 'plain';
191             $options{fh} = \$string;
192             $options{start} //= 0;
193             pica_writer( $type => %options )->write($pica);
194             return $string;
195             }
196              
197             sub pica_xml_struct {
198             my ($xml, %options) = @_;
199             my $record;
200              
201             foreach my $f (@{$xml->[2]}) {
202             next unless $f->[0] eq 'datafield';
203             push @$record, [
204             map ( { $f->[1]->{$_} } qw(tag occurrence) ),
205             map ( { $_->[1]->{code} => $_->[2]->[0] } @{$f->[2]} )
206             ]
207             }
208              
209             my ($id) = map { $_->[-1] } grep { $_->[0] =~ '003@' } @$record;
210             $record = { _id => $id, record => $record };
211             bless $record, 'PICA::Data' if !!$options{bless};
212             return $record;
213             }
214              
215             1;
216             __END__