File Coverage

blib/lib/Data/Walk/Prune.pm
Criterion Covered Total %
statement 47 57 82.4
branch 10 16 62.5
condition 3 6 50.0
subroutine 11 13 84.6
pod 1 1 100.0
total 72 93 77.4


line stmt bran cond sub pod time code
1             package Data::Walk::Prune;
2             our $AUTHORITY = 'cpan:JANDREW';
3 2     2   1075 use version; our $VERSION = version->declare('v0.26.18');
  2         3  
  2         10  
4              
5 2     2   156 use Moose::Role;
  2         3  
  2         13  
6             requires
7             '_process_the_data',
8             '_dispatch_method',
9             '_build_branch';
10 2     2   7053 use Types::Standard -types;
  2         3  
  2         18  
11             if( $ENV{ Smart_Comments } ){
12 2     2   5763 use Smart::Comments -ENV;
  2         2  
  2         14  
13             ### Smart-Comments turned on for Data-Walk-Prune ...
14             }
15              
16             #########1 Package Variables 3#########4#########5#########6#########7#########8#########9
17              
18             $| = 1;
19             my $prune_keys = {
20             slice_ref => 'primary_ref',
21             tree_ref => 'secondary_ref',
22             };
23              
24             #########1 Dispatch Tables 3#########4#########5#########6#########7#########8#########9
25              
26             my $prune_dispatch = {######<----------------------------------------- ADD New types here
27             HASH => \&_remove_hash_key,
28             ARRAY => \&_clear_array_position,
29             };
30              
31             my $remember_dispatch = {######<-------------------------------------- ADD New types here
32             HASH => \&_build_hash_cut,
33             ARRAY => \&_build_array_cut,
34             };
35              
36             my $prune_decision_dispatch = {######<------------------------------- ADD New types here
37             HASH => sub{ scalar( keys %{$_[1]->{primary_ref}} ) == 0 },
38             ARRAY => sub{ scalar( @{$_[1]->{primary_ref}} ) == 0 },
39             SCALAR => sub { return 0 },#No cut signal for SCALARS
40             UNDEF => sub { return 0 },#No cut signal for UNDEF refs
41             name => '- Prune - prune_decision_dispatch',
42             ###### Receives: the current $passed_ref
43             ###### Returns: pass | fail (Boolean style)
44             };
45              
46             #########1 Public Attributes 3#########4#########5#########6#########7#########8#########9
47              
48             has 'prune_memory' =>(
49             is => 'ro',
50             isa => Bool,
51             writer => 'set_prune_memory',
52             reader => 'get_prune_memory',
53             predicate => 'has_prune_memory',
54             clearer => 'clear_prune_memory',
55             );
56              
57             #########1 Public Methods 3#########4#########5#########6#########7#########8#########9
58              
59             sub prune_data{#Used to convert names
60             ### <where> - Made it to prune_data
61             ##### <where> - Passed input : @_
62 3     3 1 5087 my $self = $_[0];
63 3 50 33     21 my $passed_ref = ( @_ == 2 and is_HashRef( $_[1] ) ) ? $_[1] : { @_[1 .. $#_] } ;
64             ##### <where> - Passed hashref: $passed_ref
65 3         10 @$passed_ref{ 'before_method', 'after_method' } = # Hash slice
66             ( '_prune_before_method', '_prune_after_method' );
67 3         107 $self->_clear_pruned_positions;
68             ##### <where> - Start recursive parsing with: $passed_ref
69 3         12 $passed_ref = $self->_process_the_data( $passed_ref, $prune_keys );
70             ### <where> - End recursive parsing with: $passed_ref
71             ##### <where> - self: $self
72 3         35 return $passed_ref->{tree_ref};
73             }
74              
75             #########1 Private Attributes 3#########4#########5#########6#########7#########8#########9
76              
77             has '_prune_list' =>(
78             is => 'ro',
79             traits => ['Array'],
80             isa => ArrayRef[ArrayRef[Item]],
81             handles => {
82             _add_prune_item => 'push',
83             _next_prune_item => 'shift',
84             },
85             clearer => '_clear_prune_list',
86             predicate => '_has_prune_list',
87             );
88              
89             has '_pruned_positions' =>(
90             is => 'ro',
91             traits => ['Array'],
92             isa => ArrayRef[HashRef],
93             handles => {
94             _remember_prune_item => 'push',
95             number_of_cuts => 'count',
96             },
97             clearer => '_clear_pruned_positions',
98             predicate => 'has_pruned_positions',
99             reader => 'get_pruned_positions',
100             );
101              
102             #########1 Private Methods 3#########4#########5#########6#########7#########8#########9
103              
104             sub _prune_before_method{
105 16     16   13 my ( $self, $passed_ref ) = @_;
106             ### <where> - reached _prune_before_method
107             #### <where> - received input: $passed_ref
108 16 50       26 if( !exists $passed_ref->{secondary_ref} ){
109             ### <where> - no matching tree_ref element so 'skip'ing the slice node ...
110 0         0 $passed_ref->{skip} = 'YES';
111             }
112             #### <where> - skip state: $passed_ref->{skip}
113 16         25 return $passed_ref;
114             }
115              
116             sub _prune_after_method{
117 16     16   13 my ( $self, $passed_ref ) = @_;
118             ### <where> - reached _prune_after_method
119             #### <where> - received input: $passed_ref
120             ### <where> - Slice state: $self->_has_prune_list
121             ### <where> - running the cut test ...
122 16 50       28 if( $passed_ref->{skip} eq 'NO') {
123             ### <where> - The node was not skipped ...
124 16 100       33 if( $self->_dispatch_method(
    100          
125             $prune_decision_dispatch,
126             $passed_ref->{primary_type},
127             $passed_ref, ) ){
128             ### <where> - adding prune item: $passed_ref->{branch_ref}->[-1]
129 3         108 $self->_add_prune_item( $passed_ref->{branch_ref}->[-1] );
130             ### <where> - go back up and prune ...
131             }elsif( $self->_has_prune_list ){
132             my $tree_ref =
133             ( exists $passed_ref->{secondary_ref} ) ?
134 3 50       5 $passed_ref->{secondary_ref} : undef ;
135             ### <where> - tree_ref: $tree_ref
136 3         84 while( my $item_ref = $self->_next_prune_item ){
137             ### <where> - item ref: $item_ref
138 3         7 $tree_ref = $self->_prune_the_item( $item_ref, $tree_ref );
139             #### <where> - tree ref: $tree_ref
140 3 100 66     80 if( $self->has_prune_memory and
141             $self->get_prune_memory ){
142             ### <where> - building the rememberance ref ...
143 1         4 my $rememberance_ref = $self->_dispatch_method(
144             $remember_dispatch,
145             $item_ref->[0],
146             $item_ref,
147             );
148             ### <where> - current branch ref is: $passed_ref->{branch_ref}
149             $rememberance_ref = $self->_build_branch(
150             $rememberance_ref,
151 1         2 @{ $passed_ref->{branch_ref}},
  1         8  
152             );
153             ### <where> - rememberance ref: $rememberance_ref
154 1         34 $self->_remember_prune_item( $rememberance_ref );
155             #### <where> - prune memory: $self->get_pruned_positions
156             }
157             }
158 3         4 $passed_ref->{secondary_ref} = $tree_ref;
159             ### <where> - finished pruning at this node - clear the prune list ...
160 3         75 $self->_clear_prune_list;
161             }
162             }
163 16         30 return $passed_ref;
164             }
165              
166             sub _prune_the_item{
167 3     3   2 my ( $self, $item_ref, $tree_ref ) = @_;
168             ### <where> - Made it to _prune_the_item
169             ### <where> - item ref : $item_ref
170             ##### <where> - tree ref : $tree_ref
171 3         7 $tree_ref = $self->_dispatch_method(
172             $prune_dispatch,
173             $item_ref->[0],
174             $item_ref,
175             $tree_ref,
176             );
177             ### <where> - cut completed succesfully
178 3         3 return $tree_ref;
179             }
180              
181             sub _remove_hash_key{
182 3     3   3 my ( $self, $item_ref, $tree_ref ) = @_;
183             ### <where> - Made it to _remove_hash_key
184             ##### <where> - self : $self
185             ### <where> - item ref : $item_ref
186             ##### <where> - tree ref : $tree_ref
187 3         5 delete $tree_ref->{$item_ref->[1]};
188             ##### <where> - tree ref : $tree_ref
189 3         4 return $tree_ref;
190             }
191              
192             sub _clear_array_position{
193 0     0   0 my ( $self, $item_ref, $tree_ref ) = @_;
194             ### <where> - Made it to _clear_array_position
195             ### <where> - item ref : $item_ref
196             ##### <where> - tree ref : $tree_ref
197 0 0       0 if( $self->change_array_size ){
198             ### <where> - splicing out position: $item_ref->[2]
199 0         0 splice( @$tree_ref, $item_ref->[2]);
200             }else{
201             ### <where> - Setting undef at position: $item_ref->[2]
202 0         0 $tree_ref->[$item_ref->[2]] = undef;
203             }
204             ##### <where> - tree ref : $tree_ref
205 0         0 return $tree_ref;
206             }
207              
208             sub _build_hash_cut{
209 1     1   5 my ( $self, $item_ref ) = @_;
210             ### <where> - Made it to _build_hash_cut
211             ### <where> - item ref : $item_ref
212 1         3 return { $item_ref->[1] => {} };
213             }
214              
215             sub _build_array_cut{
216 0     0     my ( $self, $item_ref ) = @_;
217             ### <where> - Made it to _build_array_cut
218             ### <where> - item ref : $item_ref
219 0           my $array_ref;
220 0           $array_ref->[$item_ref->[2]] = [];
221             ### <where> - item ref : $item_ref
222 0           return $item_ref;
223             }
224              
225             #########1 Phinish Strong 3#########4#########5#########6#########7#########8#########9
226              
227 2     2   3007 no Moose::Role;
  2         2  
  2         29  
228              
229             1;
230             # The preceding line will help the module return a true value
231              
232             #########1 Main POD starts 3#########4#########5#########6#########7#########8#########9
233              
234              
235             __END__
236              
237             =head1 NAME
238              
239             Data::Walk::Prune - A way to say what should be removed
240              
241             =head1 SYNOPSIS
242              
243             #!perl
244             use Moose::Util qw( with_traits );
245             use Data::Walk::Extracted;
246             use Data::Walk::Prune;
247             use Data::Walk::Print;
248              
249             my $edward_scissorhands = with_traits(
250             'Data::Walk::Extracted',
251             (
252             'Data::Walk::Prune',
253             'Data::Walk::Print',
254             ),
255             )->new( change_array_size => 1, );#Default
256             my $firstref = {
257             Helping => [
258             'Somelevel',
259             {
260             MyKey => {
261             MiddleKey => {
262             LowerKey1 => 'low_value1',
263             LowerKey2 => {
264             BottomKey1 => 'bvalue1',
265             BottomKey2 => 'bvalue2',
266             },
267             },
268             },
269             },
270             ],
271             };
272             my $result = $edward_scissorhands->prune_data(
273             tree_ref => $firstref,
274             slice_ref => {
275             Helping => [
276             undef,
277             {
278             MyKey => {
279             MiddleKey => {
280             LowerKey1 => {},
281             },
282             },
283             },
284             ],
285             },
286             );
287             $edward_scissorhands->print_data( $result );
288              
289             ######################################################################################
290             # Output of SYNOPSIS
291             # 01 {
292             # 02 Helping => [
293             # 03 'Somelevel',
294             # 04 {
295             # 05 MyKey => {
296             # 06 MiddleKey => {
297             # 07 LowerKey2 => {
298             # 08 BottomKey1 => 'bvalue1',
299             # 09 BottomKey2 => 'bvalue2',
300             # 10 },
301             # 12 },
302             # 13 },
303             # 14 },
304             # 15 ],
305             # 16 },
306             ######################################################################################
307              
308             =head1 DESCRIPTION
309              
310             This L<Moose::Role|https://metacpan.org/module/Moose::Manual::Roles> implements the method
311             L<prune_data|/prune_data( %args )>. It takes a $tree_ref and a $slice_ref and uses
312             L<Data::Walk::Extracted|https://metacpan.org/module/Data::Walk::Extracted>. To remove
313             portions of the 'tree_ref' defined by an empty hash ref (no keys) or an empty array ref
314             (no positions) at all required points of the 'slice_ref'. The 'slice_ref' must match the
315             tree ref up to each slice point. If the slice points are on a branch of the slice_ref that
316             does not exist on the tree_ref then no cut takes place.
317              
318             =head2 USE
319              
320             This is a L<Moose::Role|https://metacpan.org/module/Moose::Manual::Roles> specifically
321             designed to be used with L<Data::Walk::Extracted
322             |https://metacpan.org/module/Data::Walk::Extracted#Extending-Data::Walk::Extracted>.
323             It can be combined traditionaly to the ~::Extracted class using L<Moose
324             |https://metacpan.org/module/Moose::Manual::Roles> methods or for information on how to join
325             this role to Data::Walk::Extracted at run time see L<Moose::Util
326             |https://metacpan.org/module/Moose::Util> or L<MooseX::ShortCut::BuildInstance
327             |https://metacpan.org/module/MooseX::ShortCut::BuildInstance> for more information.
328              
329             =head1 Attributes
330              
331             Data passed to -E<gt>new when creating an instance. For modification of these attributes
332             see L<Methods|/Methods>. The -E<gt>new function will either accept fat comma lists or a
333             complete hash ref that has the possible attributes as the top keys. Additionally
334             some attributes that have all the following methods; get_$attribute, set_$attribute,
335             has_$attribute, and clear_$attribute, can be passed to L<prune_data
336             |/prune_data( %args )> and will be adjusted for just the run of that
337             method call. These are called 'one shot' attributes. The class and each role (where
338             applicable) in this package have a list of L<supported one shot attributes
339             |/Supported one shot attributes>.
340              
341             =head2 prune_memory
342              
343             =over
344              
345             B<Definition:> When running a prune operation any branch called on the pruner
346             that does not exist in the tree will not be used. This attribute turns on tracking
347             of the actual cuts made and stores them for review after the method is complete.
348             This is a way to know if the cut was actually implemented.
349              
350             B<Default> undefined
351              
352             B<Range> 1 = remember the cuts | 0 = don't remember
353              
354             =back
355              
356             =head2 (see also)
357              
358             L<Data::Walk::Extracted|https://metacpan.org/module/Data::Walk::Extracted#Attributes>
359             - Attributes
360              
361             =head1 Methods
362              
363             =head2 prune_data( %args )
364              
365             =over
366              
367             B<Definition:> This is a method used to remove targeted parts of a data reference.
368              
369             B<Accepts:> a hash ref with the keys 'slice_ref' and 'tree_ref' (both required).
370             The slice ref can contain more than one 'slice' location in the data reference.
371              
372             =over
373              
374             B<tree_ref> This is the primary data ref that will be manipulated and returned changed.
375              
376             B<slice_ref> This is a data ref that will be used to prune the 'tree_ref'. In general
377             the slice_ref should match the tree_ref for positions that should remain unchanged.
378             Where the tree_ref should be trimmed insert either an empty array ref or an empty hash
379             ref. If this position represents a value in a hash key => value pair then the hash
380             key is deleted. If this position represents a value in an array then the position is
381             deleted/cleared depending on the attribute L<change_array_size
382             |https://metacpan.org/module/Data::Walk::Extracted#change_array_size> in
383             Data::Walk::Extracted. If the slice ref diverges from the tree ref then no action is
384             taken past the divergence, even if there is a mandated slice. (no auto vivication occurs!)
385              
386             B<[attribute name]> - attribute names are accepted with temporary attribute settings.
387             These settings are temporarily set for a single "prune_data" call and then the original
388             attribute values are restored. For this to work the the attribute must meet the
389             L<necessary criteria|/Attributes>.
390              
391             =back
392              
393             B<Example>
394              
395             $pruned_tree_ref = $self->prune_data(
396             tree_ref => $tree_data,
397             slice_ref => $slice_data,
398             prune_memory => 0,
399             );
400              
401             B<Returns:> The $tree_ref with any changes
402              
403             =back
404              
405             =head2 set_prune_memory( $Bool )
406              
407             =over
408              
409             B<Definition:> This will change the setting of the L<prune_memory|/prune_memory>
410             attribute.
411              
412             B<Accepts:> 1 = remember | 0 = no memory
413              
414             B<Returns:> nothing
415              
416             =back
417              
418             =head2 get_prune_memory
419              
420             =over
421              
422             B<Definition:> This will return the current setting of the L<prune_memory|/prune_memory>
423             attribute.
424              
425             B<Accepts:> nothing
426              
427             B<Returns:> A $Bool value for the current state
428              
429             =back
430              
431             =head2 has_prune_memory
432              
433             =over
434              
435             B<Definition:> This will indicate if the L<prune_memory|/prune_memory> attribute is set
436              
437             B<Accepts:> nothing
438              
439             B<Returns:> A $Bool value 1 = defined, 0 = not defined
440              
441             =back
442              
443             =head2 clear_prune_memory
444              
445             =over
446              
447             B<Definition:> This will clear the L<prune_memory|/prune_memory> attribute value
448             (Not the actual prune memory)
449              
450             B<Accepts:> nothing
451              
452             B<Returns:> A $Bool value 1 = defined, 0 = not defined
453              
454             =back
455              
456             =head2 has_pruned_positions
457              
458             =over
459              
460             B<Definition:> This answers if any pruned positions were stored
461              
462             B<Accepts:> nothing
463              
464             B<Returns:> A $Bool value 1 = pruned cuts are stored, 0 = no stored cuts
465              
466             =back
467              
468             =head2 get_pruned_positions
469              
470             =over
471              
472             B<Definition:> This returns an array ref of stored cuts
473              
474             B<Accepts:> nothing
475              
476             B<Returns:> an ArrayRef - although the cuts were defined in one data ref
477             this will return one data ref per cut. Each ref will go to the root of the
478             original data ref.
479              
480             =back
481              
482             =head2 number_of_cuts
483              
484             =over
485              
486             B<Definition:> This returns the number of cuts actually made
487              
488             B<Accepts:> nothing
489              
490             B<Returns:> an integer
491              
492             =back
493              
494             =head1 Caveat utilitor
495              
496             =head2 deep cloning
497              
498             Because this uses Data::Walk::Extracted the final $tree_ref is deep cloned where
499             the $slice_ref passed through.
500              
501             =head2 Supported Node types
502              
503             =over
504              
505             =item ARRAY
506              
507             =item HASH
508              
509             =item SCALAR
510              
511             =item UNDEF
512              
513             =back
514              
515             =head2 Supported one shot attributes
516              
517             L<explanation|/Attributes>
518              
519             =over
520              
521             =item prune_memory
522              
523             =back
524              
525             =head1 GLOBAL VARIABLES
526              
527             =over
528              
529             B<$ENV{Smart_Comments}>
530              
531             The module uses L<Smart::Comments|https://metacpan.org/module/Smart::Comments> if the '-ENV'
532             option is set. The 'use' is encapsulated in an if block triggered by an environmental
533             variable to comfort non-believers. Setting the variable $ENV{Smart_Comments} in a BEGIN
534             block will load and turn on smart comment reporting. There are three levels of 'Smartness'
535             available in this module '###', '####', and '#####'.
536              
537             =back
538              
539             =head1 SUPPORT
540              
541             =over
542              
543             L<github Data-Walk-Extracted/issues|https://github.com/jandrew/Data-Walk-Extracted/issues>
544              
545             =back
546              
547             =head1 TODO
548              
549             =over
550              
551             B<1.> Add L<Log::Shiras|https://metacpan.org/module/Log::Shiras> debugging in exchange for
552             L<Smart::Comments|https://metacpan.org/module/Smart::Comments>
553              
554             B<2.> Support pruning through Objects / Instances nodes
555              
556             B<3.> Support pruning through CodeRef nodes
557              
558             B<4.> Support pruning through REF nodes
559              
560             =back
561              
562             =head1 AUTHOR
563              
564             =over
565              
566             =item Jed Lund
567              
568             =item jandrew@cpan.org
569              
570             =back
571              
572             =head1 COPYRIGHT
573              
574             This program is free software; you can redistribute
575             it and/or modify it under the same terms as Perl itself.
576              
577             The full text of the license can be found in the
578             LICENSE file included with this module.
579              
580             This software is copyrighted (c) 2013 by Jed Lund.
581              
582             =head1 Dependencies
583              
584             L<version|https://metacpan.org/module/version>
585              
586             L<Moose::Role|https://metacpan.org/module/Moose::Role>
587              
588             =over
589              
590             B<requires>
591              
592             =over
593              
594             =item _process_the_data
595              
596             =item _dispatch_method
597              
598             =item _build_branch
599              
600             =back
601              
602             =back
603              
604             L<MooseX::Types::Moose|https://metacpan.org/module/MooseX::Types::Moose>
605              
606             L<Data::Walk::Extracted|https://metacpan.org/module/Data::Walk::Extracted>
607              
608             L<Data::Walk::Extracted::Dispatch|https://metacpan.org/module/Data::Walk::Extracted::Dispatch>
609              
610             =head1 SEE ALSO
611              
612             =over
613              
614             L<Smart::Comments|https://metacpan.org/module/Smart::Comments> - is used if the -ENV option is set
615              
616             L<Data::Walk|https://metacpan.org/module/Data::Walk>
617              
618             L<Data::Walker|https://metacpan.org/module/Data::Walker>
619              
620             L<Data::ModeMerge|https://metacpan.org/module/Data::ModeMerge>
621              
622             L<Data::Walk::Print|https://metacpan.org/module/Data::Walk::Print> - available Data::Walk::Extracted Role
623              
624             L<Data::Walk::Graft|https://metacpan.org/module/Data::Walk::Graft> - available Data::Walk::Extracted Role
625              
626             L<Data::Walk::Clone|https://metacpan.org/module/Data::Walk::Clone> - available Data::Walk::Extracted Role
627              
628             =back
629              
630             =cut
631              
632             #########1 Main POD ends 3#########4#########5#########6#########7#########8#########9