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