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 5     5   48549 use strict;
  5         11  
  5         134  
3 5     5   22 use warnings;
  5         10  
  5         185  
4              
5             our $VERSION = '0.32';
6              
7 5     5   25 use Exporter 'import';
  5         11  
  5         504  
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 5     5   28 use Carp qw(croak);
  5         13  
  5         309  
16 5     5   31 use Scalar::Util qw(reftype blessed);
  5         13  
  5         368  
17 5     5   36 use List::Util qw(first);
  5         10  
  5         412  
18 5     5   2597 use IO::Handle;
  5         28760  
  5         260  
19 5     5   1701 use PICA::Path;
  5         18  
  5         3560  
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 5     5   2173 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              
146             sub pica_parser {
147             _pica_module('PICA::Parser', @_)
148             }
149              
150             sub pica_writer {
151             _pica_module('PICA::Writer', @_)
152             }
153              
154             sub pica_path {
155             PICA::Path->new(@_)
156             }
157              
158             sub _pica_module {
159             my $base = shift;
160             my $type = lc(shift) // '';
161              
162             if ( $type =~ /^(pica)?plus$/ ) {
163             "${base}::Plus"->new(@_);
164             } elsif ( $type eq 'binary' ) {
165             "${base}::Binary"->new(@_);
166             } elsif ( $type =~ /^(pica)?plain$/ ) {
167             "${base}::Plain"->new(@_);
168             } elsif ( $type =~ /^(pica)?xml$/ ) {
169             "${base}::XML"->new(@_);
170             } else {
171             croak "unknown PICA parser type: $type";
172             }
173             }
174              
175             sub write {
176             my $pica = shift;
177             my $writer = $_[0];
178             unless (blessed $writer) {
179             $writer = pica_writer(@_ ? @_ : 'plain');
180             }
181             $writer->write($pica);
182             }
183              
184             sub string {
185             my ($pica, $type, %options) = @_;
186             my $string = "";
187             $type ||= 'plain';
188             $options{fh} = \$string;
189             $options{start} //= 0;
190             pica_writer( $type => %options )->write($pica);
191             return $string;
192             }
193              
194             sub pica_xml_struct {
195             my ($xml, %options) = @_;
196             my $record;
197              
198             foreach my $f (@{$xml->[2]}) {
199             next unless $f->[0] eq 'datafield';
200             push @$record, [
201             map ( { $f->[1]->{$_} } qw(tag occurrence) ),
202             map ( { $_->[1]->{code} => $_->[2]->[0] } @{$f->[2]} )
203             ]
204             }
205              
206             my ($id) = map { $_->[-1] } grep { $_->[0] =~ '003@' } @$record;
207             $record = { _id => $id, record => $record };
208             bless $record, 'PICA::Data' if !!$options{bless};
209             return $record;
210             }
211              
212             1;
213             __END__