File Coverage

blib/lib/Data/Transpose.pm
Criterion Covered Total %
statement 63 65 96.9
branch 12 14 85.7
condition n/a
subroutine 12 12 100.0
pod 4 4 100.0
total 91 95 95.7


line stmt bran cond sub pod time code
1             package Data::Transpose;
2              
3 7     7   71221 use 5.010001;
  7         14  
4 7     7   21 use strict;
  7         7  
  7         120  
5 7     7   18 use warnings;
  7         12  
  7         136  
6              
7 7     7   1838 use Data::Transpose::Field;
  7         13  
  7         178  
8 7     7   2505 use Data::Transpose::Group;
  7         13  
  7         155  
9              
10 7     7   33 use Moo;
  7         6  
  7         26  
11 7     7   1239 use MooX::Types::MooseLike::Base qw(:all);
  7         8  
  7         1639  
12 7     7   31 use namespace::clean;
  7         7  
  7         33  
13              
14             =head1 NAME
15              
16             Data::Transpose - iterate, filter and validate data, and transpose to
17             different field names
18              
19             =head1 DESCRIPTION
20              
21             Caters to your needs for manipulating data by different operations,
22             which are filtering records, iterating records, validating and
23             transposing to different field names.
24              
25             =head1 VERSION
26              
27             Version 0.0022
28              
29             =cut
30              
31             our $VERSION = '0.0022';
32              
33             =head1 SYNOPSIS
34              
35             use warnings;
36             use strict;
37            
38             use Data::Transpose::Prefix;
39             use Data::Dumper;
40            
41             my $data = {
42             first => 'John',
43             last => 'Doe',
44             foo => 'bar',
45             };
46            
47             my $dtp = Data::Transpose::Prefix->new(prefix => 'user.');
48             foreach my $needs_prefix ( qw(first last) ) {
49             $dtp->field( $needs_prefix );
50             }
51            
52             my $output = $dtp->transpose( $data );
53            
54             print Data::Dumper->Dump([$data, $output], [qw(data output)]);
55              
56             outputs:
57              
58             $data = {
59             'first' => 'John',
60             'last' => 'Doe',
61             'foo' => 'bar'
62             };
63             $output = {
64             'user.last' => 'Doe',
65             'user.first' => 'John',
66             'foo' => 'bar'
67             };
68              
69             =head1 REFERENCE
70              
71             =over 4
72              
73             =item Validator
74              
75             L
76              
77             =item Iterator
78              
79             L
80              
81             =back
82              
83             =head1 METHODS
84              
85             =head2 new
86              
87             Parameters for the constructor are:
88              
89             =over 4
90              
91             =item unknown
92              
93             Determines how to treat fields in the input hash
94             which are not known to the Data::Transpose object:
95              
96             =over 4
97              
98             =item fail
99              
100             The transpose operation fails.
101              
102             =item pass
103              
104             Unknown fields in the input hash appear in the output
105             hash. This is the default behaviour.
106              
107             =item skip
108              
109             Unknown fields in the input hash don't appear in
110             the output hash.
111              
112             =back
113              
114             This doesn't apply to the L method.
115              
116             =back
117              
118             =cut
119              
120             has unknown => (is => 'ro',
121             isa => sub {
122             my $unknown = $_[0];
123             my %permitted = (
124             fail => 1,
125             pass => 1,
126             skip => 1,
127             );
128             die "unknown accepts only " . join(' ', keys %permitted)
129             unless $permitted{$unknown};
130             },
131             default => sub { 'pass' });
132              
133             has _fields => (is => 'ro',
134             isa => ArrayRef[Object],
135             default => sub { [] },
136             );
137              
138              
139             =head2 field
140              
141             Add a new L object and return it:
142              
143             $tp->field('email');
144              
145             =cut
146              
147             sub field {
148 12     12 1 112 my ($self, $name) = @_;
149 12         13 my ($object);
150              
151 12         122 $object = Data::Transpose::Field->new(name => $name);
152              
153 12         593 push @{$self->_fields}, $object;
  12         32  
154              
155 12         42 return $object;
156             }
157              
158             =head2 group
159              
160             Add a new L object and return it:
161              
162             $tp->group('fullname', $tp->field('firstname'), $tp->field('lastname'));
163              
164             =cut
165              
166             sub group {
167 4     4 1 5 my ($self, $name, @objects) = @_;
168            
169 4         46 my $object = Data::Transpose::Group->new(name => $name,
170             objects => \@objects);
171              
172 4         355 push @{$self->_fields}, $object;
  4         9  
173            
174 4         8 return $object;
175             }
176              
177             =head2 transpose
178              
179             Transposes input:
180              
181             $new_record = $tp->transpose($orig_record);
182              
183             =cut
184              
185             sub transpose {
186 16     16 1 858 my ($self, $vref) = @_;
187 16         13 my ($weed_value, $fld_name, $new_name, %new_record, %status);
188              
189 16         55 $status{$_} = 1 for keys %$vref;
190              
191 16         20 for my $fld (@{$self->_fields}) {
  16         38  
192 24         269 $fld_name = $fld->name;
193              
194             # set value and apply operations
195 24 100       1862 if (exists $vref->{$fld_name}) {
196 16         42 $weed_value = $fld->value($vref->{$fld_name});
197             }
198             else {
199 8         17 $weed_value = $fld->value(undef);
200             }
201              
202 24 100       269 if ($new_name = $fld->target) {
203 13         93 $new_record{$new_name} = $weed_value;
204             }
205             else {
206 11         757 $new_record{$fld_name} = $weed_value;
207             }
208              
209 24         38 delete $status{$fld_name};
210             }
211              
212 16 100       39 if (keys %status) {
213             # unknown fields
214 4 100       14 if ($self->unknown eq 'pass') {
    100          
215             # pass through unknown fields
216 2         4 for (keys %status) {
217 2         5 $new_record{$_} = $vref->{$_};
218             }
219             }
220             elsif ($self->unknown eq 'fail') {
221 1         11 die "Unknown fields in input: ", join(',', keys %status), '.';
222             }
223             }
224              
225 15         37 return \%new_record;
226             }
227              
228             =head2 transpose_object
229              
230             Transposes an object into a hash reference.
231              
232             =cut
233              
234             sub transpose_object {
235 3     3 1 924 my ($self, $obj) = @_;
236 3         5 my ($weed_value, $fld_name, $new_name, %new_record, %status);
237              
238 3         3 for my $fld (@{$self->_fields}) {
  3         8  
239 3         55 $fld_name = $fld->name;
240              
241             # set value and apply operations
242 3 50       22 if ($obj->can($fld_name)) {
243 0         0 $weed_value = $fld->value($obj->$fld_name());
244             }
245             else {
246 3         8 $weed_value = $fld->value;
247             }
248              
249 3 50       19 if ($new_name = $fld->target) {
250 3         15 $new_record{$new_name} = $weed_value;
251             }
252             else {
253 0         0 $new_record{$fld_name} = $weed_value;
254             }
255             }
256              
257 3         7 return \%new_record;
258             }
259              
260             =head1 AUTHOR
261              
262             Stefan Hornburg (Racke), C<< >>
263              
264             =head1 BUGS
265              
266             Please report any bugs or feature requests at
267             L.
268             I will be notified, and then you'll
269             automatically be notified of progress on your bug as I make changes.
270              
271             =head1 SUPPORT
272              
273             You can find documentation for this module with the perldoc command.
274              
275             perldoc Data::Transpose
276              
277             You can also look for information at:
278              
279             =over 4
280              
281             =item * Github's issue tracker (report bugs here)
282              
283             L
284              
285             =item * AnnoCPAN: Annotated CPAN documentation
286              
287             L
288              
289             =item * CPAN Ratings
290              
291             L
292              
293             =item * Search CPAN
294              
295             L
296              
297             =back
298              
299              
300             =head1 ACKNOWLEDGEMENTS
301              
302             Todd Wade for mxcheck test failures fix (GH #5, #11)
303             and improvements to documentation (GH #12, #13).
304              
305             =head1 LICENSE AND COPYRIGHT
306              
307             Copyright 2012-2016 Stefan Hornburg (Racke).
308              
309             This program is free software; you can redistribute it and/or modify it
310             under the terms of either: the GNU General Public License as published
311             by the Free Software Foundation; or the Artistic License.
312              
313             See http://dev.perl.org/licenses/ for more information.
314              
315              
316             =cut
317              
318             1; # End of Data::Transpose