File Coverage

blib/lib/Catmandu/Fix/mab_map.pm
Criterion Covered Total %
statement 60 65 92.3
branch 13 20 65.0
condition 2 4 50.0
subroutine 6 6 100.0
pod 0 1 0.0
total 81 96 84.3


line stmt bran cond sub pod time code
1             package Catmandu::Fix::mab_map;
2              
3              
4             our $VERSION = '0.23';
5              
6 4     4   12799 use Catmandu::Sane;
  4         10  
  4         21  
7 4     4   593 use Carp qw(confess);
  4         9  
  4         169  
8 4     4   19 use Moo;
  4         8  
  4         28  
9 4     4   2372 use Catmandu::Fix::Has;
  4         2342  
  4         25  
10              
11             has mab_path => ( fix_arg => 1 );
12             has path => ( fix_arg => 1 );
13             has record => ( fix_opt => 1 );
14             has split => ( fix_opt => 1 );
15             has join => ( fix_opt => 1 );
16             has value => ( fix_opt => 1 );
17             has pluck => ( fix_opt => 1 );
18              
19             sub emit {
20 7     7 0 40554 my ( $self, $fixer ) = @_;
21 7         30 my $path = $fixer->split_path( $self->path );
22 7   50     208 my $record_key = $fixer->emit_string( $self->record // 'record' );
23 7   50     82 my $join_char = $fixer->emit_string( $self->join // '' );
24 7         48 my $mab_path = $self->mab_path;
25              
26 7         11 my $field_regex;
27 7         16 my ( $field, $ind, $subfield_regex, $from, $to );
28              
29 7 100       33 if ( $mab_path
30             =~ /(\S{3})(\[(.+)\])?([_a-z0-9]+)?(\/(\d+)(-(\d+))?)?/ )
31             {
32 6         13 $field = $1;
33 6         11 $ind = $3;
34 6 100       17 $subfield_regex = defined $4 ? "[$4]" : "[_A-Za-z0-9]";
35 6         10 $from = $6;
36 6         10 $to = $8;
37             }
38             else {
39 1         14 Catmandu::Error->throw('invalid mab path');
40             }
41              
42 6         9 $field_regex = $field;
43 6         11 $field_regex =~ s/\*/./g;
44              
45 6         99 my $var = $fixer->var;
46 6         47 my $vals = $fixer->generate_var;
47 6         57 my $perl = $fixer->emit_declare_vars( $vals, '[]' );
48              
49             $perl .= $fixer->emit_foreach(
50             "${var}->{${record_key}}",
51             sub {
52 6     6   128 my $var = shift;
53 6         14 my $v = $fixer->generate_var;
54 6         40 my $perl = "";
55              
56 6         17 $perl .= "next if ${var}->[0] !~ /${field_regex}/;";
57              
58 6 100       14 if (defined $ind) {
59 1         3 $perl .= "next if (!defined ${var}->[1] || ${var}->[1] ne '${ind}');";
60             }
61              
62 6 50       19 if ( $self->value ) {
63 0         0 $perl .= $fixer->emit_declare_vars( $v,
64             $fixer->emit_string( $self->value ) );
65             }
66             else {
67 6         12 my $i = $fixer->generate_var;
68             my $add_subfields = sub {
69 6         10 my $start = shift;
70 6 100       13 if ($self->pluck) {
71             # Treat the subfield_regex as a hash index
72 1         3 my $pluck = $fixer->generate_var;
73             return
74 1         15 "my ${pluck} = {};" .
75             "for (my ${i} = ${start}; ${i} < \@{${var}}; ${i} += 2) {".
76             "push(\@{ ${pluck}->{ ${var}->[${i}] } }, ${var}->[${i} + 1]);" .
77             "}" .
78             "for my ${i} (split('','${subfield_regex}')) { " .
79             "push(\@{${v}}, \@{ ${pluck}->{${i}} }) if exists ${pluck}->{${i}};" .
80             "}";
81             }
82             else {
83             # Treat the subfield_regex as regex that needs to match the subfields
84             return
85 5         46 "for (my ${i} = ${start}; ${i} < \@{${var}}; ${i} += 2) {".
86             "if (${var}->[${i}] =~ /${subfield_regex}/) {".
87             "push(\@{${v}}, ${var}->[${i} + 1]);".
88             "}".
89             "}";
90             }
91 6         53 };
92 6         14 $perl .= $fixer->emit_declare_vars( $v, "[]" );
93 6         55 $perl .= $add_subfields->(2);
94 6         16 $perl .= "if (\@{${v}}) {";
95 6 50       22 if ( !$self->split ) {
96 6         17 $perl .= "${v} = join(${join_char}, \@{${v}});";
97 6 50       19 if ( defined( my $off = $from ) ) {
98 0 0       0 my $len = defined $to ? $to - $off + 1 : 1;
99 0         0 $perl .= "if (eval { ${v} = substr(${v}, ${off}, ${len}); 1 }) {";
100             }
101             }
102             $perl .= $fixer->emit_create_path(
103             $fixer->var,
104             $path,
105             sub {
106 6         341 my $var = shift;
107 6 50       15 if ( $self->split ) {
108 0         0 "if (is_array_ref(${var})) {"
109             . "push \@{${var}}, ${v};"
110             . "} else {"
111             . "${var} = [${v}];" . "}";
112             }
113             else {
114 6         38 "if (is_string(${var})) {"
115             . "${var} = join(${join_char}, ${var}, ${v});"
116             . "} else {"
117             . "${var} = ${v};" . "}";
118             }
119             }
120 6         112 );
121 6 50       60 if ( defined($from) ) {
122 0         0 $perl .= "}";
123             }
124 6         42 $perl .= "}";
125             }
126 6         13 $perl;
127             }
128 6         115 );
129              
130 6         72 $perl;
131             }
132              
133             1;
134              
135             __END__
136              
137             =pod
138              
139             =encoding UTF-8
140              
141             =head1 NAME
142              
143             Catmandu::Fix::mab_map - copy mab values of one field to a new field
144              
145             =head1 SYNOPSIS
146              
147             # Copy all 245 subfields into the my.title hash
148             mab_map('245','my.title');
149              
150             # Copy the 245-$a$b$c subfields into the my.title hash
151             mab_map('245abc','my.title');
152              
153             # Copy the 100 subfields into the my.authors array
154             mab_map('100','my.authors.$append');
155            
156             # Add the 710 subfields into the my.authors array
157             mab_map('710','my.authors.$append');
158              
159             # Copy the 600-$x subfields into the my.subjects array while packing each into a genre.text hash
160             mab_map('600x','my.subjects.$append', -in => 'genre.text');
161              
162             # Copy the 008 characters 35-35 into the my.language hash
163             mab_map('008_/35-35','my.language');
164              
165             # Copy all the 600 fields into a my.stringy hash joining them by '; '
166             mab_map('600','my.stringy', -join => '; ');
167              
168             # When 024 field exists create the my.has024 hash with value 'found'
169             mab_map('024','my.has024', -value => 'found');
170              
171             # Do the same examples now with the fields in 'record2'
172             mab_map('245','my.title', -record => 'record2');
173              
174             =head1 AUTHOR
175              
176             Johann Rolschewski <jorol@cpan.org>
177              
178             =head1 COPYRIGHT AND LICENSE
179              
180             This software is copyright (c) 2013 by Johann Rolschewski.
181              
182             This is free software; you can redistribute it and/or modify it under
183             the same terms as the Perl 5 programming language system itself.
184              
185             =cut