File Coverage

blib/lib/Catmandu/Fix/Bind/visitor.pm
Criterion Covered Total %
statement 39 45 86.6
branch 10 16 62.5
condition n/a
subroutine 7 8 87.5
pod 0 4 0.0
total 56 73 76.7


line stmt bran cond sub pod time code
1              
2             use Catmandu::Sane;
3 1     1   1329  
  1         3  
  1         10  
4             our $VERSION = '1.2018';
5              
6             use Moo;
7 1     1   9 use Catmandu::Util;
  1         2  
  1         9  
8 1     1   409 use namespace::clean;
  1         2  
  1         69  
9 1     1   7  
  1         1  
  1         49  
10             with 'Catmandu::Fix::Bind', 'Catmandu::Fix::Bind::Group';
11              
12             has path => (is => 'ro');
13              
14             my ($self, $data) = @_;
15              
16 18     18 0 46 if (defined $self->path) {
17             return Catmandu::Util::data_at($self->path, $data);
18 18 50       70 }
19 0         0 else {
20             return $data;
21             }
22 18         252 }
23              
24             my ($self, $mvar, $func) = @_;
25              
26             if (Catmandu::Util::is_array_ref($mvar)) {
27             return $self->bind_array($mvar, $func, '');
28             }
29             elsif (Catmandu::Util::is_hash_ref($mvar)) {
30             return $self->bind_hash($mvar, $func, '');
31             }
32             else {
33             return $self->bind_hash($mvar, $func, '');
34             }
35             }
36              
37             my ($self, $mvar, $func, $parent) = @_;
38              
39             return $func->({'key' => $parent, 'scalar' => $mvar})->{'scalar'};
40             }
41 0     0 0 0  
42             my ($self, $mvar, $func, $parent) = @_;
43 0         0  
44             my $result = $func->({'key' => $parent, 'array' => $mvar});
45              
46             my $new_var = [];
47 1     1 0 4  
48             for (my $i = 0; $i < @$mvar; $i++) {
49 1         19 my $item = $mvar->[$i];
50             if (Catmandu::Util::is_array_ref($item)) {
51 1         3 my ($newkey, $newvalue) = $self->bind_array($item, $func, $i);
52             $mvar->[$i] = $newvalue;
53 1         4 }
54 2         5 elsif (Catmandu::Util::is_hash_ref($item)) {
55 2 50       9 my ($newkey, $newvalue) = $self->bind_hash($item, $func, $i);
    50          
56 0         0 $mvar->[$i] = $newvalue;
57 0         0 }
58             else {
59             $mvar->[$i]
60 2         6 = $func->({'key' => $i, 'scalar' => $item})->{'scalar'};
61 2         7 }
62             }
63              
64             return ($result->{key}, $result->{array});
65 0         0 }
66              
67             my ($self, $mvar, $func, $parent) = @_;
68              
69 1         5 my $result = $func->({'key' => $parent, 'hash' => $mvar});
70              
71             for my $key (keys %$mvar) {
72             my $item = $mvar->{$key};
73 25     25 0 52  
74             if (Catmandu::Util::is_array_ref($item)) {
75 25         388  
76             # Keys can update themselves
77 25         86 my ($newkey, $newvalue) = $self->bind_array($item, $func, $key);
78 53         89 $mvar->{$newkey} = $newvalue;
79             delete $mvar->{$key} if ($newkey ne $key);
80 53 100       148 }
    100          
81             elsif (Catmandu::Util::is_hash_ref($item)) {
82              
83 1         5 # Keys can update themselves
84 1         3 my ($newkey, $newvalue) = $self->bind_hash($item, $func, $key);
85 1 50       4 $mvar->{$newkey} = $newvalue;
86             delete $mvar->{$key} if ($newkey ne $key);
87             }
88             else {
89             # Keys can update themselves
90 5         14 my $result = $func->({'key' => $key, 'scalar' => $item});
91 5         12 $mvar->{$result->{'key'}} = $result->{'scalar'};
92 5 50       13 delete $mvar->{$key} if ($result->{'key'} ne $key);
93             }
94             }
95              
96 47         699 return ($result->{key}, $result->{hash});
97 47         99 }
98 47 50       195  
99             1;
100              
101              
102 25         87 =pod
103              
104             =head1 NAME
105              
106             Catmandu::Fix::Bind::visitor - a binder that computes Fix-es for every element in record
107              
108             =head1 SYNOPSIS
109              
110             # If data is like:
111              
112             numbers:
113             - one
114             - two
115             - three
116             person:
117             name: jennie
118             age: 44
119             color:
120             - green
121             - purple
122             - brown
123             - more:
124             foo: bar
125              
126             do visitor()
127             upcase(scalar) # upcase every scalar value in the record
128             end
129              
130             # will produce
131              
132             numbers:
133             - ONE
134             - TWO
135             - THREE
136             person:
137             name: JENNIE
138             age: 44
139             color:
140             - GREEN
141             - PURPLE
142             - BROWN
143             - more:
144             foo: BAR
145              
146             do visitor()
147             # upcase all the 'name' fields in the record
148             if all_match(key,name)
149             upcase(scalar)
150             end
151             end
152              
153             do visitor()
154             # upcase all the field names in the record
155             upcase(key)
156             end
157              
158             =head1 DESCRIPTION
159              
160             The visitor binder will iterate over all the elements in a record and perform fixes on them.
161              
162             Special node names are available to process every visited element:
163              
164             =over 4
165              
166             =item scalar
167              
168             Process a Fix on every scalar value. E.g.
169              
170             upcase(scalar)
171             replace_all(scalar,'$','tested')
172              
173             =item array
174              
175             Process a Fix on every array value. E.g.
176              
177             sort_field(array)
178              
179             Values need to be put in the 'array' field to be available for fixes. The scope of
180             the array is limited to the array visited.
181              
182             =item hash
183              
184             Process a Fix on every hash value. E.g.
185              
186             copy_field(hash.age,hash.age2)
187              
188             Values need to be put in the 'hash' field to be available for fixes. The scope of
189             the hash is limited to the hash visited.
190              
191             =item key
192              
193             Provides access to the key on which the scalar,array or hash value is found. Eg.
194              
195             # Upcase all 'name' fields in the record
196             if all_match(key,name)
197             upcase(scalar)
198             end
199              
200             =back
201              
202             =head1 CONFIGURATION
203              
204             =head2 path
205              
206             A path in the data to visit:
207              
208             # Visit any field
209             do visitor()
210             ...
211             end
212              
213             # Visit only the fields at my.deep.field
214             do visitor(path: my.deep.field)
215             ...
216             end
217              
218             =head1 SEE ALSO
219              
220             L<Catmandu::Fix::Bind>
221              
222             =cut