File Coverage

blib/lib/Data/Walk/Extracted.pm
Criterion Covered Total %
statement 222 256 86.7
branch 76 104 73.0
condition 22 40 55.0
subroutine 36 38 94.7
pod n/a
total 356 438 81.2


line stmt bran cond sub pod time code
1             package Data::Walk::Extracted;
2             our $AUTHORITY = 'cpan:JANDREW';
3 5     5   1817574 use version 0.77; our $VERSION = version->declare('v0.26.16');
  5         79  
  5         27  
4 5     5   412 use 5.010;
  5         12  
5 5     5   19 use Moose 2.1803;
  5         46  
  5         22  
6 5     5   22318 use MooseX::StrictConstructor;
  5         65555  
  5         14  
7 5     5   30179 use MooseX::HasDefaults::RO;
  5         22942  
  5         17  
8 5     5   31811 use Class::Inspector;
  5         12305  
  5         148  
9 5     5   29 use Scalar::Util qw( reftype );
  5         7  
  5         274  
10 5     5   20 use Carp qw( confess );
  5         4  
  5         240  
11 5         44 use Types::Standard qw(
12             Str is_Str ArrayRef is_ArrayRef
13             HashRef is_HashRef Int Bool
14             CodeRef is_CodeRef Object is_Object
15 5     5   20 );
  5         6  
16             if( $ENV{ Smart_Comments } ){
17 5     5   7914 use Smart::Comments -ENV;
  5         68439  
  5         30  
18             ### Smart-Comments turned on for Data-Walk-Extracted ...
19             }
20 5     5   16998 use lib '../../../lib';
  5         7  
  5         37  
21 5         28 use Data::Walk::Extracted::Types 0.024 qw(
22             PosInt
23 5     5   2283 );
  5         99  
24             with 'Data::Walk::Extracted::Dispatch' =>{ -VERSION => 0.026 };
25              
26             #########1 Package Variables 3#########4#########5#########6#########7#########8#########9
27              
28             $| = 1;
29             my $wait;
30             my $data_key_tests = {
31             required => [ qw(
32             primary_ref
33             ) ],
34             at_least_one => [ qw(
35             before_method
36             after_method
37             ) ],
38             all_possibilities => {
39             secondary_ref => 1,
40             branch_ref => 1,
41             },
42             };
43             # Adding elements from the firts two keys to all ...
44             for my $key ( @{$data_key_tests->{required}}, @{$data_key_tests->{at_least_one}} ){
45             $data_key_tests->{all_possibilities}->{$key} = 1;
46             }
47             my $base_type_ref ={
48             SCALAR => 1,
49             UNDEF => 1,
50             };
51              
52             my @data_key_list = qw(
53             primary_ref
54             secondary_ref
55             );
56              
57             my @lower_key_list = qw(
58             primary_type
59             secondary_type
60             match
61             skip
62             );
63              
64             # This is also the order of type investigaiton testing
65             # This is the maximum list of types -but-
66             # if the types are also not listed in the appropriate dispatch
67             # tables, then it still won't parse
68             my $supported_type_list = [ qw(
69             UNDEF SCALAR CODEREF OBJECT ARRAY HASH
70             ) ];######<------------------------------------------------------ ADD New types here
71              
72             #########1 Dispatch Tables 3#########4#########5#########6#########7#########8#########9
73              
74             my $node_list_dispatch = {######<---------------------------------- ADD New types here
75             name => '- Extracted - node_list_dispatch',#Meta data
76             HASH => sub{ [ keys %{$_[1]} ] },
77             ARRAY => sub{
78             my $list;
79             map{ push @$list, 1 } @{$_[1]};
80             return $list;
81             },
82             SCALAR => sub{ [ $_[1] ] },
83             OBJECT => \&_get_object_list,
84             ###### Receives: a data reference or scalar
85             ###### Returns: an array reference of list items
86             };
87              
88             my $main_down_level_data ={
89             ###### Purpose: Used to build the generic elements of the next passed ref down
90             ###### Recieves: the upper ref value
91             ###### Returns: the lower ref value or undef
92             name => '- Extracted - main down level data',
93             DEFAULT => sub{ undef },
94             before_method => sub{ return $_[1] },
95             after_method => sub{ return $_[1] },
96             branch_ref => \&_main_down_level_branch_ref,
97             };
98              
99             my $down_level_tests_dispatch ={
100             ###### Purpose: Used to test the down level item elements
101             ###### Recieves: the lower ref
102             ###### Returns: the lower level test result
103             name => '- Extracted - item down level data',
104             primary_type => &_item_down_level_type( 'primary_ref' ),
105             secondary_type => &_item_down_level_type( 'secondary_ref' ),
106             match => \&_ref_matching,
107             skip => \&_will_parse_next_ref,
108             };
109              
110             my $sub_ref_dispatch = {######<------------------------------------ ADD New types here
111             name => '- Extracted - sub_ref_dispatch',#Meta data
112             HASH => sub{ return $_[1]->{$_[2]} },
113             ARRAY => sub{ return $_[1]->[$_[3]] },
114             SCALAR => sub{ return undef; },
115             OBJECT => \&_get_object_element,
116             ###### Receives: a upper data reference, an item, and a position
117             ###### Returns: a lower array reference
118             };
119              
120             my $discover_type_dispatch = {######<------------------------------- ADD New types here
121             UNDEF => sub{ !$_[1] },
122             SCALAR => sub{ is_Str( $_[1] ) },
123             ARRAY => sub{ is_ArrayRef( $_[1] ) },
124             HASH => sub{ is_HashRef( $_[1] ) },
125             OBJECT => sub{ is_Object( $_[1] ) },
126             CODEREF => sub{ is_CodeRef( $_[1] ) },
127             };
128              
129             my $secondary_match_dispatch = {######<----------------------------- ADD New types here
130             name => '- Extracted - secondary_match_dispatch',#Meta data
131             DEFAULT => sub{ return 'YES' },
132             SCALAR => sub{
133             return ( $_[1]->{primary_ref} eq $_[1]->{secondary_ref} ) ?
134             'YES' : 'NO' ;
135             },
136             OBJECT => sub{
137             return ( ref( $_[1]->{primary_ref} ) eq ref( $_[1]->{secondary_ref} ) ) ?
138             'YES' : 'NO' ;
139             },
140             ###### Receives: the next $passed_ref, the item, and the item postion
141             ###### Returns: YES or NO
142             ###### Non-existent and non matching lower ref types should have already been eliminated
143             };
144              
145             my $up_ref_dispatch = {######<-------------------------------------- ADD New types here
146             name => '- Extracted - up_ref_dispatch',#Meta data
147             HASH => \&_load_hash_up,
148             ARRAY => \&_load_array_up,
149             SCALAR => sub{
150             ### <where> - made it to SCALAR ref upload ...
151             $_[3]->{$_[1]} = $_[2]->[1];
152             ### <where> - returning: $_[3]
153             return $_[3];
154             },
155             OBJECT => \&_load_object_up,
156             ###### Receives: the data ref key, the lower branch_ref element,
157             ###### and the upper and lower data refs
158             ###### Returns: the upper data ref
159             };
160              
161             my $object_extraction_dispatch ={######<---------------------------- ADD New types here
162             name => '- Extracted - object_extraction_dispatch',
163             HASH => sub{ return {%{$_[1]}} },
164             ARRAY => sub{ return [@{$_[1]}] },
165             DEFAULT => sub{ return ${$_[1]} },
166             ###### Receives: an object reference
167             ###### Returns: a reference or string of the blessed data in the object
168             };
169              
170             my $secondary_ref_exists_dispatch ={######<------------------------- ADD New types here
171             name => '- Extracted - secondary_ref_exists_dispatch',
172             HASH => sub{
173             ### <where> - passed: @_
174             exists $_[1]->{secondary_ref} and
175             is_HashRef( $_[1]->{secondary_ref} ) and
176             exists $_[1]->{secondary_ref}->{$_[2]}
177             },
178             ARRAY => sub{
179             exists $_[1]->{secondary_ref} and
180             is_ArrayRef( $_[1]->{secondary_ref} ) and
181             exists $_[1]->{secondary_ref}->[$_[3]]
182             },
183             SCALAR => sub{ exists $_[1]->{secondary_ref} },
184             ###### Receives: the upper ref, the current list item, and the current position
185             ###### Returns: pass or fail (pass means continue)
186             };
187              
188             my $reconstruction_dispatch = {######<----------------------------- ADD New types here
189             name => 'reconstruction_dispatch',#Meta data
190             HASH => \&_rebuild_hash_level,
191             ARRAY => \&_rebuild_array_level,
192             };
193              
194             #########1 Public Attributes 3#########4#########5#########6#########7#########8#########9
195              
196             has 'sorted_nodes' =>(
197             is => 'ro',
198             isa => HashRef,
199             traits => ['Hash'],
200             default => sub{ {} },
201             handles => {
202             add_sorted_nodes => 'set',
203             has_sorted_nodes => 'count',
204             check_sorted_node => 'exists',
205             clear_sorted_nodes => 'clear',
206             remove_sorted_node => 'delete',
207             _retrieve_sorted_nodes => 'get',
208             },
209             writer => 'set_sorted_nodes',
210             reader => 'get_sorted_nodes',
211             );
212              
213             has 'skipped_nodes' =>(
214             is => 'ro',
215             isa => HashRef,
216             traits => ['Hash'],
217             default => sub{ {} },
218             handles => {
219             add_skipped_nodes => 'set',
220             has_skipped_nodes => 'count',
221             check_skipped_node => 'exists',
222             clear_skipped_nodes => 'clear',
223             remove_skipped_node => 'delete',
224             },
225             writer => 'set_skipped_nodes',
226             reader => 'get_skipped_nodes',
227             );
228              
229             has 'skip_level' =>(
230             is => 'ro',
231             isa => Int,
232             predicate => 'has_skip_level',
233             reader => 'get_skip_level',
234             writer => 'set_skip_level',
235             clearer => 'clear_skip_level',
236             );
237              
238             has 'skip_node_tests' =>(
239             is => 'ro',
240             isa => ArrayRef[ArrayRef],
241             traits => ['Array'],
242             reader => 'get_skip_node_tests',
243             writer => 'set_skip_node_tests',
244             default => sub{ [] },
245             handles => {
246             add_skip_node_test => 'push',
247             has_skip_node_tests => 'count',
248             clear_skip_node_tests => 'clear',
249             },
250             );
251              
252             has 'change_array_size' =>(
253             is => 'ro',
254             isa => Bool,
255             predicate => 'has_change_array_size',
256             reader => 'get_change_array_size',
257             writer => 'set_change_array_size',
258             clearer => 'clear_change_array_size',
259             default => 1,
260             );
261              
262             has 'fixed_primary' =>(
263             is => 'ro',
264             isa => Bool,
265             predicate => 'has_fixed_primary',
266             reader => 'get_fixed_primary',
267             writer => 'set_fixed_primary',
268             clearer => 'clear_fixed_primary',
269             default => 0,
270             );
271              
272             #########1 Private Attributes 3#########4#########5#########6#########7#########8#########9
273              
274             has '_current_level' =>(
275             is => 'ro',
276             isa => PosInt,
277             default => 0,
278             writer => '_set_current_level',
279             reader => '_get_current_level',
280             );
281              
282             has '_had_secondary' =>(
283             is => 'ro',
284             isa => Bool,
285             writer => '_set_had_secondary',
286             reader => '_get_had_secondary',
287             predicate => '_has_had_secondary',
288             default => 0,
289             );
290              
291             sub _clear_had_secondary{
292 49     49   39 my ( $self, ) = @_;
293             ### <where> - setting _had_secondary to 0 ...
294 49         1339 $self->_set_had_secondary( 0 );
295 49         36 return 1;
296             }
297              
298             has '_single_pass_attributes' =>(
299             is => 'ro',
300             isa => ArrayRef[HashRef],
301             traits => ['Array'],
302             default => sub{ [] },
303             handles => {
304             _levels_of_saved_attributes => 'count',
305             _add_saved_attribute_level => 'push',
306             _get_saved_attribute_level => 'pop',
307             },
308             );
309              
310             #########1 Methods for Roles 3#########4#########5#########6#########7#########8#########9
311              
312             sub _process_the_data{#Used to scrub high level input
313             ### <where> - Made it to _process_the_data
314             ##### <where> - Passed input : @_
315 51     51   51 my ( $self, $passed_ref, $conversion_ref, ) = @_;
316             ### <where> - review the ref keys for requirements and conversion ...
317 51         40 my $return_conversion;
318 51         93 ( $passed_ref, $return_conversion ) =
319             $self->_convert_data( $passed_ref, $conversion_ref );
320             #### <where> - new passed_ref: $passed_ref
321 51         86 $self->_has_required_inputs( $passed_ref, $return_conversion );
322 49         81 $passed_ref = $self->_has_at_least_one_input( $passed_ref, $return_conversion );
323 49         78 $passed_ref = $self->_manage_the_rest( $passed_ref );
324             ##### <where> - Start recursive parsing with: $passed_ref
325 49         86 my $return_ref = $self->_walk_the_data( $passed_ref );
326             ### <where> - convert the data keys back to the role names
327 49         70 ( $return_ref, $conversion_ref ) =
328             $self->_convert_data( $return_ref, $return_conversion );
329             ### <where> - restoring instance clone attributes as needed ...
330 49         94 $self->_restore_attributes;
331 49         80 $self->_clear_had_secondary;
332             ##### <where> - End recursive parsing with: $return_ref
333 49         111 return $return_ref;
334             }
335              
336             sub _build_branch{
337 11     11   14 my ( $self, $base_ref, @arg_list ) = @_;
338             ## <where> - Made it to _build_branch ...
339             ### <where> - base ref : $base_ref
340             ##### <where> - the passed arguments : @arg_list
341 11 100       23 if( $arg_list[-1]->[3] == 0 ){
    50          
342             ### <where> - zeroth level found: @arg_list
343 3         10 return $base_ref;
344             }elsif( @arg_list ){
345 8         9 my $current_ref = pop @arg_list;
346 8         15 $base_ref = $self->_dispatch_method(
347             $reconstruction_dispatch ,
348             $current_ref->[0],
349             $current_ref,
350             $base_ref,
351             );
352 8         21 my $answer = $self->_build_branch( $base_ref, @arg_list );
353             ### <where> - back up with : $answer
354 8         73 return $answer;
355             }else{
356             ### <where> - reached the bottom - returning: $base_ref
357 0         0 return $base_ref;
358             }
359              
360             }
361              
362             #########1 Private Methods 3#########4#########5#########6#########7#########8#########9
363              
364             sub _walk_the_data{
365 257     257   200 my( $self, $passed_ref ) = @_;
366             ### <where> - Made it to _walk_the_data
367             ##### <where> - Passed input : $passed_ref
368             ### <where> - running the before_method ...
369 257 50       304 if( exists $passed_ref->{before_method} ){
370 257         213 my $before_method = $passed_ref->{before_method};
371             ### <where> - role has a before_method: $before_method
372 257         625 $passed_ref = $self->$before_method( $passed_ref );
373             ### <where> - completed before_method
374             #### <where> - the current passed ref is: $passed_ref
375             }else{
376             ### <where> - No before_method found
377             }
378             ### <where> - See if the node should be parsed ...
379 257         186 my $list_ref;
380 257 100       538 if( $passed_ref->{skip} eq 'YES' ){
    100          
381             ### <where> - Skip condition identified ...
382             }elsif( exists $base_type_ref->{$passed_ref->{primary_type}} ){
383             ### <where> - base type identified as: $passed_ref->{primary_type}
384             }else{
385             ### <where> - get the lower ref list ...
386             $list_ref = $self->_dispatch_method(
387             $node_list_dispatch,
388             $passed_ref->{primary_type},
389             $passed_ref->{primary_ref},
390 141         293 );
391             ### <where> - sorting the list as needed for: $list_ref
392 141 100       4384 if( $self->check_sorted_node( $passed_ref->{primary_type} ) ){
393             ### <where> - The list should be sorted ...
394             my $sort_function =
395             ( is_CodeRef(
396             $self->_retrieve_sorted_nodes( $passed_ref->{primary_type} )
397             ) ) ? ######## ONLY PARTIALLY TESTED !!!! ######
398             $self->_retrieve_sorted_nodes( $passed_ref->{primary_type} ) :
399 44 50   23   1331 sub{ $a cmp $b } ;
  23         50  
400 44         103 $list_ref = [ sort $sort_function @$list_ref ];
401 44 50       148 if( $passed_ref->{primary_type} eq 'ARRAY' ){
402             ### <where> - This is an array ref and the array ref will be sorted ...
403             $passed_ref->{primary_ref} =
404 0         0 [sort $sort_function @{$passed_ref->{primary_ref}}];
  0         0  
405             }
406             ##### <where> - sorted list: $list_ref
407             }
408             }
409 257 100       366 if( $list_ref ){
410             ### <where> - climbing up the node tree ...
411             #### <where> - running the list: $list_ref
412 139         3731 $self->_set_current_level( 1 + $self->_get_current_level );
413             #### <where> - new current level: $self->_get_current_level
414 139         230 my $lower_ref = $self->_down_load_general( $passed_ref );
415             #### <where> - the core lower ref is: $lower_ref
416 139         110 my $x = 0;
417 139         102 for my $item ( @{$list_ref} ){
  139         151  
418             ### <where> - now parsing: $item
419 208         180 delete $lower_ref->{secondary_ref};
420 208         5933 $lower_ref = $self->_get_lower_refs(
421             $passed_ref, $lower_ref, $item,
422             $x, $self->_get_current_level,
423             );
424             #### <where>- lower ref: $lower_ref
425 208         210 for my $key ( @lower_key_list ){
426             ### <where> - working to load: $key
427 832         1239 $lower_ref->{$key} = $self->_dispatch_method(
428             $down_level_tests_dispatch, $key, $lower_ref,
429             );
430             }
431             ##### <where> - walking the data: $lower_ref
432 208         390 $lower_ref = $self->_walk_the_data( $lower_ref );
433 208         156 my $old_branch_ref = pop @{$lower_ref->{branch_ref}};
  208         246  
434             ### <where> - pass any data reference adjustments upward ...
435             #### <where> - using branch ref: $old_branch_ref
436 208         332 for my $key ( @data_key_list ){
437             ### <where> - processing: $key
438 416 50 66     6483 if( $key eq 'primary_ref' and
    100 66        
439             $self->has_fixed_primary and
440             $self->get_fixed_primary ){
441             ### <where> - the primary ref is fixed and no changes will be passed upwards ...
442             }elsif( exists $lower_ref->{$key} ){
443             ### <where> - a lower ref was identified and will be passed upwards for: $key
444 349         652 $passed_ref = $self->_dispatch_method(
445             $up_ref_dispatch,
446             $old_branch_ref->[0],
447             $key,
448             $old_branch_ref,
449             $passed_ref,
450             $lower_ref,
451             );
452             }
453             #### <where> - new passed ref: $passed_ref
454             }
455 208         305 $x++;
456             }
457             ### <where> - climbing back down the node tree ...
458             #### <where> - current level: $self->_get_current_level
459 139         3763 $self->_set_current_level( -1 + $self->_get_current_level );
460             }
461              
462             ### <where> - running the after_method ...
463 257 100       314 if( exists $passed_ref->{after_method} ){
464 214         203 my $after_method = $passed_ref->{after_method};
465             ### <where> - role has an after_method: $after_method
466 214         443 $passed_ref = $self->$after_method( $passed_ref );
467             #### <where> - returned from after_method: $passed_ref
468             }else{
469             ### <where> - No after_method found
470             }
471             #### <where> - returning passedref: $passed_ref
472 257         311 return $passed_ref;
473             }
474              
475             sub _convert_data{
476 100     100   86 my ( $self, $passed_ref, $conversion_ref, ) = @_;
477             ### <where> - reached _convert_data ...
478             #### <where> - conversion ref: $conversion_ref
479             #### <where> - passed ref: $passed_ref
480 100         214 for my $key ( keys %$conversion_ref ){
481 154 100       257 if( exists $passed_ref->{$key} ){
482             $passed_ref->{$conversion_ref->{$key}} =
483             ( $passed_ref->{$key} ) ?
484 134 100       265 $passed_ref->{$key} : undef;
485 134         171 delete $passed_ref->{$key};
486             }
487             }
488             ### <where> - inverting conversion ref ...
489 100         227 my $return_conversion = { reverse %$conversion_ref };
490             ### <where> - passed ref now equals: $passed_ref
491 100         141 return( $passed_ref, $return_conversion );
492             }
493              
494             sub _has_required_inputs{
495 51     51   38 my ( $self, $passed_ref, $lookup_ref, ) = @_;
496             ### <where> - Made it to _has_required_inputs ...
497             ##### <where> - Passed ref: $passed_ref
498             ##### <where> - Lookup ref: $lookup_ref
499 51         47 for my $key ( @{$data_key_tests->{required}} ){
  51         88  
500 51 100       104 if( !exists $passed_ref->{$key} ){
501             confess '-' .
502 2 50       30 ( ( exists $lookup_ref->{$key} ) ? $lookup_ref->{$key} : $key ) .
503             '- is a required key but was not found in the passed ref';
504             }
505             }
506 49         49 return 1;
507             }
508              
509             sub _has_at_least_one_input{
510 49     49   38 my ( $self, $passed_ref, $lookup_ref ) = @_;
511             ### <where> - Made it to _has_at_least_one_input ...
512             ##### <where> - Passed ref: $passed_ref
513             ##### <where> - Lookup ref: $lookup_ref
514 49         32 my $count;
515 49         37 for my $key ( @{$data_key_tests->{at_least_one}} ){
  49         66  
516 98 100       170 if( !exists $passed_ref->{$key} ){
    50          
517 12         36 push @{$count->{missing}}, (
518             ( exists $lookup_ref->{$key} ) ?
519 12 50       6 $lookup_ref->{$key} : $key
520             );
521             }elsif( defined $passed_ref->{$key} ){
522 86         119 $count->{found}++;
523             }else{
524 0         0 push @{$count->{empty}}, (
525             ( exists $lookup_ref->{$key} ) ?
526 0 0       0 $lookup_ref->{$key} : $key
527             );
528 0         0 delete $passed_ref->{$key};
529             }
530             }
531 49 50       65 if( $count->{found} ){
    0          
532 49         90 return $passed_ref;
533             }elsif( exists $count->{empty} ){
534 0         0 confess '-' . (join '- and -', @{$count->{empty}} ) .
  0         0  
535             '- must have values for the key(s)';
536             }else{
537 0         0 confess 'One of the keys -' . (join '- or -', @{$count->{missing}} ) .
  0         0  
538             '- must be provided with values';
539             }
540             }
541              
542             sub _manage_the_rest{
543 49     49   41 my ( $self, $passed_ref ) = @_;
544             ### <where> - Made it to _manage_the_rest ...
545             ### <where> - Passed ref: $passed_ref
546             ### <where> - load a passed branch_ref ...
547             $passed_ref->{branch_ref} = $self->_main_down_level_branch_ref(
548             $passed_ref->{branch_ref}
549 49         118 );
550             ### <where> - handle one shot attributes ...
551 49         68 my $attributes_at_level = {};
552 49         103 for my $key ( keys %$passed_ref ){
553 206 100       284 if( exists $data_key_tests->{all_possibilities}->{$key} ){
    50          
554             ### <where> - found standard key: $key
555             }elsif( $self->meta->find_attribute_by_name( $key ) ){
556             ### <where> - found an attribute: $key
557 5         375 $key =~ /^(_)?([^_].*)/;
558 5         26 my ( $predicate, $writer, $reader, $clearer ) =
559             ( "has_$2", "set_$2", "get_$2", "clear_$2", );
560 5 50       13 if( defined $1 ){
561 0         0 ( $predicate, $writer, $reader, $clearer ) =
562             ( "_$predicate", "_$writer", "_$reader", "_$clearer" );
563             }
564             ### <where> - Testing for attribute use as a "one-shot" attribute ...
565 5         10 for my $method ( $predicate, $reader, $writer, $clearer ){
566 20 50       90 if( $self->can( $method ) ){
567             ### <where> - so far so good for: $method
568             }else{
569 0         0 confess "-$method- is not supported for key -$key- " .
570             "so one shot attribute test failed";
571             }
572             }
573             ### <where> - First save the old settings ...
574 5 100       176 $attributes_at_level->{$key} = ( $self->$predicate ) ?
575             $self->$reader : undef;
576             ### <where> - load the new settings: $passed_ref->{$key}
577 5         146 $self->$writer( $passed_ref->{$key} );
578 5         14 delete $passed_ref->{$key};
579             }else{
580 0         0 confess "-$key- is not an accepted hash key value";
581             }
582             }
583             #### <where> - attribute storage: $attributes_at_level
584 49         1825 $self->_add_saved_attribute_level( $attributes_at_level );
585             ### <where> - setting the secondary flag as needed ...
586 49 100       92 if( exists $passed_ref->{secondary_ref} ){
587 17         465 $self->_set_had_secondary( 1 );
588             }
589             ### <where> - setting the remaining keys ...
590 49         61 for my $key ( @lower_key_list ){
591             ### <where> - working to load: $key
592 196         341 $passed_ref->{$key} = $self->_dispatch_method(
593             $down_level_tests_dispatch, $key, $passed_ref,
594             );
595             }
596             #### <where> - current passed ref: $passed_ref
597             ##### <where> - self: $self
598 49         57 return $passed_ref;
599             }
600              
601             sub _main_down_level_branch_ref{
602 188     188   183 my ( $self, $value ) = @_;
603             ### <where> - reached _main_down_level_branch_ref ...
604 188   100     384 $value //= [ [ 'SCALAR', undef, 0, 0, ] ];
605             #### <where> - using: $value
606 188         115 my $return;
607 188         194 map{ push @$return, $_ } @$value;
  430         493  
608             ### <where> - returning: $return
609 188         268 return $return;
610             }
611              
612             sub _get_object_list{
613 0     0   0 my ( $self, $data_reference ) = @_;
614             ### <where> - Made it to _get_object_list ...
615             ##### <where> - passed reference: $data_reference
616 0         0 my $list_ref;
617 0 0       0 if( scalar( @{$self->_get_object_attributes( $data_reference )} ) ){
  0         0  
618             ### <where> - found attributes ...
619 0         0 push @$list_ref, 'attributes';
620             }
621 0 0       0 if( scalar( @{$self->_get_object_methods( $data_reference )} ) ){
  0         0  
622             ### <where> - found methods ...
623 0         0 push @$list_ref, 'methods';
624             }
625             ### <where> - final list: $list_ref
626 0         0 return $list_ref;
627             }
628              
629             sub _down_load_general{
630 139     139   117 my( $self, $upper_ref, ) = @_;
631             ### <where> - reached _down_load_general ...
632             #### <where> - upper ref: $upper_ref
633 139         110 my $lower_ref;
634 139         338 for my $key ( keys %$upper_ref ){
635             my $return = $self->_dispatch_method(
636 1140         1660 $main_down_level_data, $key, $upper_ref->{$key},
637             );
638 1140 100       1774 $lower_ref->{$key} = $return if defined $return;
639             }
640             #### <where> - returning lower_ref: $lower_ref
641 139         175 return $lower_ref;
642             }
643              
644             sub _restore_attributes{
645 49     49   98 my ( $self, ) = @_;
646 49         44 my ( $answer, ) = (0, );
647             ### <where> - reached _restore_attributes ...
648 49         1641 my $attribute_ref = $self->_get_saved_attribute_level;
649 49         94 for my $attribute ( keys %$attribute_ref ){
650             ### <where> - restoring: $attribute
651 5         13 $attribute =~ /^(_)?([^_].*)/;
652 5         18 my ( $writer, $clearer ) = ( "set_$2", "clear_$2", );
653 5 50       12 if( defined $1 ){
654 0         0 ( $writer, $clearer ) = ( "_$writer", "_$clearer" );
655             }
656             ### <where> - possible clearer: $clearer
657             ### <where> - possible writer: $writer
658 5         160 $self->$clearer;
659 5 100       12 if( defined $attribute_ref->{$attribute} ){
660             ### <where> - resetting attribute value: $attribute_ref->{$attribute}
661 2         55 $self->$writer( $attribute_ref->{$attribute} );
662             }
663             ### <where> - finished restoring: $attribute
664             }
665 49         68 return 1;
666             }
667              
668             sub _item_down_level_type{
669 10     10   8 my ( $key ) = @_;
670             return sub{
671 514     514   390 my ( $self, $passed_ref, ) = @_;
672 514         529 return $self->_extracted_ref_type(
673             $key, $passed_ref,
674             );
675             }
676 10         33 }
677              
678             sub _extracted_ref_type{
679 514     514   417 my ( $self, $ref_key, $passed_ref, ) = @_;
680             ### <where> - made it to _extracted_ref_type ...
681 514         338 my $ref_type;
682 514 100       591 if( exists $passed_ref->{$ref_key} ){
683 329         350 $ref_type = ref $passed_ref->{$ref_key};
684 329 100       404 if( exists $discover_type_dispatch->{$ref_type} ){
685             ### <where> - confirmed ref: $ref_type
686             }else{
687 123         117 CHECKALLTYPES: for my $key ( @$supported_type_list ){
688             ### <where> - testing: $key
689 249 100       418 if( $self->_dispatch_method(
690             $discover_type_dispatch,
691             $key,
692             $passed_ref->{$ref_key},
693             ) ){
694             ### <where> - found a match for: $key
695 123         76 $ref_type = $key;
696 123         158 last CHECKALLTYPES;
697             }
698             ### <where> - no match ...
699             }
700             }
701             }else{
702 185         147 $ref_type = 'DNE';
703             }
704             ##### <where> - ref type is: $ref_type
705 514 50       647 if( !$ref_type ){
706 0         0 confess "Attempting to parse the unsupported node type -" .
707             ( ref $passed_ref ) . "-";
708             }
709             ### <where> - returning: $ref_type
710 514         1009 return $ref_type;
711             }
712              
713             sub _ref_matching{
714 257     257   186 my ( $self, $passed_ref, ) = @_;
715             ### <where> - reached _ref_matching ...
716             ### <where> - matching for type: $passed_ref->{branch_ref}->[-1]->[0]
717             ##### <where> - passed items: @_
718 257         188 my $match = 'NO';
719 257 100       373 if( $passed_ref->{secondary_type} eq 'DNE' ){
    100          
720             ### <where> - nothing to match ...
721             }elsif( $passed_ref->{secondary_type} ne $passed_ref->{primary_type} ){
722             ### <where> - failed a type match ...
723             }else{
724             ### <where> - The obvious match issues pass - testing deeper ...
725             $match = $self->_dispatch_method(
726             $secondary_match_dispatch, $passed_ref->{primary_type},
727 58         56 $passed_ref, @{$passed_ref->{branch_ref}->[-1]}[1,2],
  58         136  
728             );
729             }
730             ### <where> - returning: $match
731 257         445 return $match;
732             }
733              
734             sub _will_parse_next_ref{
735 257     257   203 my ( $self, $passed_ref, ) = @_;
736             ### <where> - Made it to _will_parse_next_ref ...
737             #### <where> - Passed ref: $passed_ref
738 257         185 my $skip = 'NO';
739 257 100 100     8261 if( $self->has_skipped_nodes and
    100 100        
    100          
740             $self->check_skipped_node( $passed_ref->{primary_type} ) ){
741             ### <where> - skipping the current nodetype: $passed_ref->{primary_type}
742 4         6 $skip = 'YES';
743             }elsif($self->has_skip_level and
744             $self->get_skip_level ==
745             ( ( $passed_ref->{branch_ref}->[-1]->[3] ) + 1 ) ){
746             ### <where> - skipping the level: ( $passed_ref->{branch_ref}->[-1]->[3] + 1 )
747 5         5 $skip = 'YES';
748             }elsif( $self->has_skip_node_tests ){
749 16         14 my $current_branch = $passed_ref->{branch_ref}->[-1];
750             ### <where> - found skip tests: $self->get_skip_node_tests
751 16         10 SKIPNODE: for my $test ( @{$self->get_skip_node_tests} ){
  16         446  
752             ### <where> - running test: $test
753 16         20 $skip = $self->_general_skip_node_test(
754             $test, $current_branch,
755             );
756 16 100       29 last SKIPNODE if $skip eq 'YES';
757             }
758             }
759             ### <where> - returning skip eq: $skip
760 257         744 return $skip;
761             }
762              
763             sub _general_skip_node_test{
764 16     16   17 my ( $self, $test_ref, $branch_ref, ) = @_;
765 16         12 my $match_level= 0;
766             ### <where> - reached _general_skip_node_test ...
767             ### <where> - test_ref: $test_ref
768             ### <where> - branch_ref: $branch_ref
769 16         14 my $item = $branch_ref->[1];
770             ### <where> - item: $item
771 16 100       27 $match_level++ if
772             ( $test_ref->[0] eq $branch_ref->[0] );
773             ### <where> - match level after type match: $match_level
774 16 100 66     170 $match_level++ if
      66        
      66        
      66        
775             (
776             ( $test_ref->[1] eq 'ARRAY' ) or
777             ( $test_ref->[1] =~ /^(any|all)$/i ) or
778             ( $item and
779             (
780             $test_ref->[1] eq $item or
781             $test_ref->[1] =~ /$item/
782             )
783             )
784             );
785             ### <where> - match level after item match: $match_level
786 16 50 0     44 $match_level++ if
      33        
787             ( $test_ref->[2] =~ /^(any|all)$/i or
788             ( is_Num( $test_ref->[2] ) and
789             $test_ref->[2] == $branch_ref->[2] ) );
790             ### <where> - match level after position match: $match_level
791 16 50 0     44 $match_level++ if
      33        
792             ( $test_ref->[3] =~ /^(any|all)$/i or
793             ( is_Num( $test_ref->[3] ) and
794             $test_ref->[3] == $branch_ref->[3] ) );
795             ### <where> - match level after depth match: $match_level
796 16 100       20 my $answer = ( $match_level == 4 ) ? 'YES' : 'NO' ;
797             ### <where> - answer: $answer
798 16         22 return $answer;
799             }
800              
801             sub _get_lower_refs{
802 208     208   217 my ( $self, $upper_ref, $lower_ref, $item, $position, $level ) = @_;
803             ### <where> - reached _get_lower_refs ...
804             ##### <where> - passed: @_
805 208         212 for my $key ( @data_key_list ){
806             ### <where> - running key: $key
807 416         290 my $test = 1;
808 416 100       568 if( $key eq 'secondary_ref' ){
809             ###<where> - secondary ref check ...
810             $test = $self->_dispatch_method(
811             $secondary_ref_exists_dispatch,
812             $upper_ref->{primary_type},
813 208         319 $upper_ref, $item, $position,
814             );
815             ### <where> - secondary ref exists result: $test
816             }
817 416 100       560 if( $test ){
818             ### <where> - loading lower ref needed ...
819             $lower_ref->{$key} = $self->_dispatch_method(
820             $sub_ref_dispatch,
821             $upper_ref->{primary_type},
822 263         514 $upper_ref->{$key}, $item, $position,
823             );
824             }
825             ##### <where> - lower_ref: $lower_ref
826             }
827 208         449 push @{$lower_ref->{branch_ref}}, [
828             $upper_ref->{primary_type},
829 208         162 $item, $position, $level,
830             ];
831             #### <where> - returning: $lower_ref
832 208         232 return $lower_ref;
833             }
834              
835             sub _get_object_element{
836 0     0   0 my ( $self, $data_reference, $item, $position, ) = @_;
837             ### <where> - Made it to _get_object_attributes ...
838             #### <where> - data reference: $data_reference
839             #### <where> - data reference: $item
840             #### <where> - data reference: $position
841 0         0 my $item_ref;
842 0 0       0 if( $item eq 'attributes' ){
843 0         0 my $scalar_util_val = reftype( $data_reference );
844 0   0     0 $scalar_util_val //= 'DEFAULT';
845             ### <where> - Scalar-Util-reftype: $scalar_util_val
846 0         0 $item_ref = $self->_dispatch_method(
847             $object_extraction_dispatch,
848             $scalar_util_val,
849             $data_reference,
850             );
851 0 0       0 }if( $item eq 'methods' ){
852 0         0 $item_ref = Class::Inspector->function_refs(
853             ref $data_reference
854             );
855             }else{
856 0         0 confess "Get -$item- element not written yet";
857             }
858             ### <where> - the attribute list is: $item_ref
859 0         0 return $item_ref;
860             }
861              
862             sub _load_hash_up{
863 239     239   243 my ( $self, $key, $branch_ref_item, $passed_ref, $lower_passed_ref, ) = @_;
864             ### <where> - Made it to _load_hash_up for the: $key
865             ### <where> - the branch ref is: $branch_ref_item
866             ##### <where> - passed info: @_
867             $passed_ref->{$key}->{$branch_ref_item->[1]} =
868 239         303 $lower_passed_ref->{$key};
869             ##### <where> - the new passed_ref is: $passed_ref
870 239         436 return $passed_ref;
871             }
872              
873             sub _load_array_up{
874 110     110   101 my ( $self, $key, $branch_ref_item, $passed_ref, $lower_passed_ref, ) = @_;
875             ### <where> - Made it to _load_array_up for the: $key
876             ### <where> - the branch ref is: $branch_ref_item
877             ##### <where> - lower ref: $lower_passed_ref
878             $passed_ref->{$key}->[$branch_ref_item->[2]] =
879 110         143 $lower_passed_ref->{$key};
880             ##### <where> - the new passed_ref is: $passed_ref
881 110         218 return $passed_ref;
882             }
883              
884             sub _rebuild_hash_level{
885 6     6   8 my ( $self, $item_ref, $base_ref, ) = @_;
886             ### <where> - Made it to _rebuild_hash_level
887             ### <where> - item ref : $item_ref
888             ### <where> - base ref : $base_ref
889 6         15 return { $item_ref->[1] => $base_ref };
890             }
891              
892             sub _rebuild_array_level{
893 2     2   3 my ( $self, $item_ref, $base_ref, ) = @_;
894             ### <where> - Made it to _rebuild_array_level
895             ### <where> - item ref : $item_ref
896             ### <where> - base ref : $base_ref
897 2         3 my $array_ref = [];
898 2         6 $array_ref->[$item_ref->[2]] = $base_ref;
899 2         4 return $array_ref;
900             }
901              
902             #########1 Phinish Strong 3#########4#########5#########6#########7#########8#########9
903              
904 5     5   15028 no Moose;
  5         8  
  5         38  
905             __PACKAGE__->meta->make_immutable;
906              
907             1;
908             # The preceding line will help the module return a true value
909              
910             #########1 Main POD starts 3#########4#########5#########6#########7#########8#########9
911              
912             __END__
913              
914             =head1 NAME
915              
916             Data::Walk::Extracted - An extracted dataref walker
917              
918             =begin html
919              
920             <a href="https://www.perl.org">
921             <img src="https://img.shields.io/badge/perl-5.10+-brightgreen.svg" alt="perl version">
922             </a>
923              
924             <a href="https://travis-ci.org/jandrew/Data-Walk-Extracted">
925             <img alt="Build Status" src="https://travis-ci.org/jandrew/Data-Walk-Extracted.png?branch=master" alt='Travis Build'/>
926             </a>
927              
928             <a href='https://coveralls.io/r/jandrew/Data-Walk-Extracted?branch=master'>
929             <img src='https://coveralls.io/repos/jandrew/Data-Walk-Extracted/badge.svg?branch=master' alt='Coverage Status' />
930             </a>
931              
932             <a href='https://github.com/jandrew/Data-Walk-Extracted'>
933             <img src="https://img.shields.io/github/tag/jandrew/Data-Walk-Extracted.svg?label=github version" alt="github version"/>
934             </a>
935              
936             <a href="https://metacpan.org/pod/Data::Walk::Extracted">
937             <img src="https://badge.fury.io/pl/Data-Walk-Extracted.svg?label=cpan version" alt="CPAN version" height="20">
938             </a>
939              
940             <a href='http://cpants.cpanauthors.org/dist/Data-Walk-Extracted'>
941             <img src='http://cpants.cpanauthors.org/dist/Data-Walk-Extracted.png' alt='kwalitee' height="20"/>
942             </a>
943              
944             =end html
945              
946             =head1 SYNOPSIS
947              
948             This is a contrived example! For a more functional (complex/useful) example see the
949             roles in this package.
950              
951             package Data::Walk::MyRole;
952             use Moose::Role;
953             requires '_process_the_data';
954             use MooseX::Types::Moose qw(
955             Str
956             ArrayRef
957             HashRef
958             );
959             my $mangle_keys = {
960             Hello_ref => 'primary_ref',
961             World_ref => 'secondary_ref',
962             };
963              
964             #########1 Public Method 3#########4#########5#########6#########7#########8
965              
966             sub mangle_data{
967             my ( $self, $passed_ref ) = @_;
968             @$passed_ref{ 'before_method', 'after_method' } =
969             ( '_mangle_data_before_method', '_mangle_data_after_method' );
970             ### Start recursive parsing
971             $passed_ref = $self->_process_the_data( $passed_ref, $mangle_keys );
972             ### End recursive parsing with: $passed_ref
973             return $passed_ref->{Hello_ref};
974             }
975              
976             #########1 Private Methods 3#########4#########5#########6#########7#########8
977              
978             ### If you are at the string level merge the two references
979             sub _mangle_data_before_method{
980             my ( $self, $passed_ref ) = @_;
981             if(
982             is_Str( $passed_ref->{primary_ref} ) and
983             is_Str( $passed_ref->{secondary_ref} ) ){
984             $passed_ref->{primary_ref} .= " " . $passed_ref->{secondary_ref};
985             }
986             return $passed_ref;
987             }
988              
989             ### Strip the reference layers on the way out
990             sub _mangle_data_after_method{
991             my ( $self, $passed_ref ) = @_;
992             if( is_ArrayRef( $passed_ref->{primary_ref} ) ){
993             $passed_ref->{primary_ref} = $passed_ref->{primary_ref}->[0];
994             }elsif( is_HashRef( $passed_ref->{primary_ref} ) ){
995             $passed_ref->{primary_ref} = $passed_ref->{primary_ref}->{level};
996             }
997             return $passed_ref;
998             }
999              
1000             package main;
1001             use MooseX::ShortCut::BuildInstance qw(
1002             build_instance
1003             );
1004             my $AT_ST = build_instance(
1005             package => 'Greeting',
1006             superclasses => [ 'Data::Walk::Extracted' ],
1007             roles => [ 'Data::Walk::MyRole' ],
1008             );
1009             print $AT_ST->mangle_data( {
1010             Hello_ref =>{ level =>[ { level =>[ 'Hello' ] } ] },
1011             World_ref =>{ level =>[ { level =>[ 'World' ] } ] },
1012             } ) . "\n";
1013              
1014              
1015              
1016             #################################################################################
1017             # Output of SYNOPSIS
1018             # 01:Hello World
1019             #################################################################################
1020              
1021             =head1 DESCRIPTION
1022              
1023             This module takes a data reference (or two) and
1024             L<recursivly|http://en.wikipedia.org/wiki/Recursion_(computer_science)>
1025             travels through it(them). Where the two references diverge the walker follows the
1026             primary data reference. At the L<beginning|/Assess and implement the before_method>
1027             and L<end|/Assess and implement the after_method> of each branch or L<node|/node>
1028             in the data the code will attempt to call a L<method|/Extending Data::Walk::Extracted>
1029             on the remaining unparsed data.
1030              
1031             =head2 Acknowledgement of MJD
1032              
1033             This is an implementation of the concept of extracted data walking from
1034             L<Higher-Order-Perl|http://hop.perl.plover.com/book/> Chapter 1 by
1035             L<Mark Jason Dominus|https://metacpan.org/author/MJD>. I<The book is well worth the
1036             money!> With that said I diverged from MJD purity in two ways. This is object oriented
1037             code not functional code. Second, when taking action the code will search for class
1038             methods provided by (your) role rather than acting on passed closures. There is clearly
1039             some overhead associated with both of these differences. I made those choices consciously
1040             and if that upsets you L<do not hassle MJD|/AUTHOR>!
1041              
1042             =head2 What is the unique value of this module?
1043              
1044             With the recursive part of data walking extracted the various functionalities desired
1045             when walking the data can be modularized without copying this code. The Moose
1046             framework also allows diverse and targeted data parsing without dragging along a
1047             L<kitchen sink|http://en.wiktionary.org/wiki/everything_but_the_kitchen_sink> API
1048             for every use of this class.
1049              
1050             =head2 Extending Data::Walk::Extracted
1051              
1052             B<All action taken during the data walking must be initiated by implementation of action
1053             methods that do not exist in this class>. It usually also makes sense to build an
1054             initial action method as well. The initial action method can do any data-preprocessing
1055             that is useful as well as providing the necessary set up for the generic walker. All
1056             of these elements can be combined with this class using a L<Moose role
1057             |https://metacpan.org/module/Moose::Manual::Roles>, by
1058             L<extending the class|https://metacpan.org/module/Moose::Manual::Classes>, or it can be
1059             joined to the class at run time. See L<MooseX::ShortCut::BuildInstance
1060             |https://metacpan.org/module/MooseX::ShortCut::BuildInstance>. or L<Moose::Util
1061             |https://metacpan.org/module/Moose::Util> for more class building information. See the
1062             L<parsing flow|/Recursive Parsing Flow> to understand the details of how the methods are
1063             used. See L<methods used to write roles|/Methods used to write roles> for the available
1064             methods to implement the roles.
1065              
1066             Then, L<Write some tests for your role!|http://www.perlmonks.org/?node_id=918837>
1067              
1068             =head1 Recursive Parsing Flow
1069              
1070             =head2 Initial data input and scrubbing
1071              
1072             The primary input method added to this class for external use is refered to as
1073             the 'action' method (ex. 'mangle_data'). This action method needs to receive
1074             data and organize it for sending to the L<start method
1075             |/_process_the_data( $passed_ref, $conversion_ref )> for the generic data walker.
1076             I<Remember if more than one role is added to Data::Walk::Extracted
1077             for a given instance then all methods should be named with consideration for other
1078             (future?) method names. The '$conversion_ref' allows for muliple uses of the core
1079             data walkers generic functions. The $conversion_ref is not passed deeper into the
1080             recursion flow.>
1081              
1082             =head2 Assess and implement the before_method
1083              
1084             The class next checks for an available 'before_method'. Using the test;
1085              
1086             exists $passed_ref->{before_method};
1087              
1088             If the test passes then the next sequence is run.
1089              
1090             $method = $passed_ref->{before_method};
1091             $passed_ref = $self->$method( $passed_ref );
1092              
1093             If the $passed_ref is modified by the 'before_method' then the recursive parser will
1094             parse the new ref and not the old one. The before_method can set;
1095              
1096             $passed_ref->{skip} = 'YES'
1097              
1098             Then the flow checks for the need to investigate deeper.
1099              
1100             =head2 Test for deeper investigation
1101              
1102             The code now checks if deeper investigation is required checking both that the 'skip' key
1103             = 'YES' in the $passed_ref or if the node is a L<base ref type|/base node type>.
1104             If either case is true the process jumps to the L<after method
1105             |/Assess and implement the after_method> otherwise it begins to investigate the next
1106             level.
1107              
1108             =head2 Identify node elements
1109              
1110             If the next level in is not skipped then a list is generated for all L<paths|/node>
1111             in the node. For example a 'HASH' node would generate a list of hash keys for that node.
1112             SCALAR nodes will generate a list with only one element containing the scalar contents.
1113             UNDEF nodes will generate an empty list.
1114              
1115             =head2 Sort the node as required
1116              
1117             If the list L<should be sorted|/sorted_nodes>
1118             then the list is sorted. B<ARRAYS are hard sorted.> I<This means that the actual items in
1119             the (primary) passed data ref are permanantly sorted.>
1120              
1121             =head2 Process each element
1122              
1123             For each identified element of the node a new $data_ref is generated containing data that
1124             represents just that sub element. The secondary_ref is only constructed if it has a
1125             matching type and element to the primary ref. Matching for hashrefs is done by key
1126             matching only. Matching for arrayrefs is done by position exists testing only. I<No
1127             position content compare is done!> Scalars are matched on content. The list of items
1128             generated for this element is as follows;
1129              
1130             =over
1131              
1132             B<before_method =E<gt>> --E<gt>name of before method for this role hereE<lt>--
1133              
1134             B<after_method =E<gt>> --E<gt>name of after method for this role hereE<lt>--
1135              
1136             B<primary_ref =E<gt>> the piece of the primary data ref below this element
1137              
1138             B<primary_type =E<gt>> the lower primary (walker)
1139             L<ref type|/_extracted_ref_type( $test_ref )>
1140              
1141             B<match =E<gt>> YES|NO (This indicates if the secondary ref meets matching critera
1142              
1143             B<skip =E<gt>> YES|NO Checks L<the three skip attributes|/skipped_nodes> against
1144             the lower primary_ref node. This can also be set in the 'before_method' upon arrival
1145             at that node.
1146              
1147             B<secondary_ref =E<gt>> if match eq 'YES' then built like the primary ref
1148              
1149             B<secondary_type =E<gt>> if match eq 'YES' then calculated like the primary type
1150              
1151             B<branch_ref =E<gt>> L<stack trace|/A position trace is generated>
1152              
1153             =back
1154              
1155             =head2 A position trace is generated
1156              
1157             The current node list position is then documented and pushed onto the array at
1158             $passed_ref->{branch_ref}. The array reference stored in branch_ref can be
1159             thought of as the stack trace that documents the node elements directly between the
1160             current position and the initial (or zeroth) level of the parsed primary data_ref.
1161             Past completed branches and future pending branches are not maintained. Each element
1162             of the branch_ref contains four positions used to describe the node and selections
1163             used to traverse that node level. The values in each sub position are;
1164              
1165             [
1166             ref_type, #The node reference type
1167             the list item value or '' for ARRAYs,
1168             #key name for hashes, scalar value for scalars
1169             element sequence position (from 0),
1170             #For hashes this is only relevent if sort_HASH is called
1171             level of the node (from 0),
1172             `#The zeroth level is the initial data ref
1173             ]
1174              
1175             =head2 Going deeper in the data
1176              
1177             The down level ref is then passed as a new data set to be parsed and it starts
1178             at the L<before_method|/Assess and implement the before_method> again.
1179              
1180             =head2 Actions on return from recursion
1181              
1182             When the values are returned from the recursion call the last branch_ref element is
1183             L<pop|http://perldoc.perl.org/functions/pop.html>ed off and the returned data ref
1184             is used to L<replace|/fixed_primary> the sub elements of the primary_ref and secondary_ref
1185             associated with that list element in the current level of the $passed_ref. If there are
1186             still pending items in the node element list then the program L<processes them too
1187             |/Process each element>
1188              
1189              
1190             =head2 Assess and implement the after_method
1191              
1192             After the node elements have all been processed the class checks for an available
1193             'after_method' using the test;
1194              
1195             exists $passed_ref->{after_method};
1196              
1197             If the test passes then the following sequence is run.
1198              
1199             $method = $passed_ref->{after_method};
1200             $passed_ref = $self->$method( $passed_ref );
1201              
1202             If the $passed_ref is modified by the 'after_method' then the recursive parser will
1203             parse the new ref and not the old one.
1204              
1205             =head2 Go up
1206              
1207             The updated $passed_ref is passed back up to the L<next level
1208             |/Actions on return from recursion>.
1209              
1210             =head1 Attributes
1211              
1212             Data passed to -E<gt>new when creating an instance. For modification of these attributes
1213             see L<Public Methods|/Public Methods>. The -E<gt>new function will either accept fat
1214             comma lists or a complete hash ref that has the possible attributes as the top keys.
1215             Additionally some attributes that have the following prefixed methods; get_$name, set_$name,
1216             clear_$name, and has_$name can be passed to L<_process_the_data
1217             |/_process_the_data( $passed_ref, $conversion_ref )> and will be adjusted for just the
1218             run of that method call. These are called L<one shot|/Supported one shot attributes>
1219             attributes. Nested calls to _process_the_data will be tracked and the attribute will
1220             remain in force until the parser returns to the calling 'one shot' level. Previous
1221             attribute values are restored after the 'one shot' attribute value expires.
1222              
1223             =head2 sorted_nodes
1224              
1225             =over
1226              
1227             B<Definition:> If the primary_type of the L<$element_ref|/Process each element>
1228             is a key in this attribute hash ref then the node L<list|/Identify node elements> is
1229             sorted. If the value of that key is a CODEREF then the sort L<sort
1230             |http://perldoc.perl.org/functions/sort.html> function will called as follows.
1231              
1232             @node_list = sort $coderef @node_list
1233              
1234             I<For the type 'ARRAY' the node is sorted (permanantly) by the element values. This
1235             means that if the array contains a list of references it will effectivly sort against
1236             the ASCII of the memory pointers. Additionally the 'secondary_ref' node is not
1237             sorted, so prior alignment may break. In general ARRAY sorts are not recommended.>
1238              
1239             B<Default> {} #Nothing is sorted
1240              
1241             B<Range> This accepts a HashRef.
1242              
1243             B<Example:>
1244              
1245             sorted_nodes =>{
1246             ARRAY => 1,#Will sort the primary_ref only
1247             HASH => sub{ $b cmp $a }, #reverse sort the keys
1248             }
1249              
1250             =back
1251              
1252             =head2 skipped_nodes
1253              
1254             =over
1255              
1256             B<Definition:> If the primary_type of the L<$element_ref|/Process each element>
1257             is a key in this attribute hash ref then the 'before_method' and 'after_method' are
1258             run at that node but no L<parsing|/Identify node elements> is done.
1259              
1260             B<Default> {} #Nothing is skipped
1261              
1262             B<Range> This accepts a HashRef.
1263              
1264             B<Example:>
1265              
1266             sorted_nodes =>{
1267             OBJECT => 1,#skips all object nodes
1268             }
1269              
1270             =back
1271              
1272             =head2 skip_level
1273              
1274             =over
1275              
1276             B<Definition:> This attribute is set to skip (or not) node parsing at the set level.
1277             Because the process doesn't start checking until after it enters the data ref
1278             it effectivly ignores a skip_level set to 0 (The base node level). I<The test checks
1279             against the value in last position of the prior L<trace|/A position trace is generated>
1280             array ref + 1>.
1281              
1282             B<Default> undef = Nothing is skipped
1283              
1284             B<Range> This accepts an integer
1285              
1286             =back
1287              
1288             =head2 skip_node_tests
1289              
1290             =over
1291              
1292             B<Definition:> This attribute contains a list of test conditions used to skip
1293             certain targeted nodes. The test can target an array position, match a hash key, even
1294             restrict the test to only one level. The test is run against the latest
1295             L<branch_ref|/A position trace is generated> element so it skips the node below the
1296             matching conditions not the node at the matching conditions. Matching is done with
1297             '=~' and so will accept a regex or a string. The attribute contains an ArrayRef of
1298             ArrayRefs. Each sub_ref contains the following;
1299              
1300             =over
1301              
1302             B<$type> - This is any of the L<identified|/_extracted_ref_type( $test_ref )>
1303             reference node types
1304              
1305             B<$key> - This is either a scalar or regex to use for matching a hash key
1306              
1307             B<$position> - This is used to match an array position. It can be an integer or 'ANY'
1308              
1309             B<$level> - This restricts the skipping test usage to a specific level only or 'ANY'
1310              
1311             =back
1312              
1313             B<Example:>
1314              
1315             [
1316             [ 'HASH', 'KeyWord', 'ANY', 'ANY'],
1317             # Skip the node below the value of any hash key eq 'Keyword'
1318             [ 'ARRAY', 'ANY', '3', '4'], ],
1319             # Skip the node stored in arrays at position three on level four
1320             ]
1321              
1322             B<Range> An infinite number of skip tests added to an array
1323              
1324             B<Default> [] = no nodes are skipped
1325              
1326             =back
1327              
1328             =head2 change_array_size
1329              
1330             =over
1331              
1332             B<Definition:> This attribute will not be used by this class directly. However
1333             the L<Data::Walk::Prune|https://metacpan.org/module/Data::Walk::Prune#prune_data-args>
1334             role may share it with other roles in the future so it is placed here so there will be
1335             no conflicts. This is usually used to define whether an array size shinks when an element
1336             is removed.
1337              
1338             B<Default> 1 (This probably means that the array will shrink when a position is removed)
1339              
1340             B<Range> Boolean values.
1341              
1342             =back
1343              
1344             =head2 fixed_primary
1345              
1346             =over
1347              
1348             B<Definition:> This means that no changes made at lower levels will be passed
1349             upwards into the final ref.
1350              
1351             B<Default> 0 = The primary ref is not fixed (and can be changed) I<0 -E<gt> effectively
1352             deep clones the portions of the primary ref that are traversed.>
1353              
1354             B<Range> Boolean values.
1355              
1356             =back
1357              
1358             =head1 Methods
1359              
1360             =head2 Methods used to write roles
1361              
1362             These are methods that are not meant to be exposed to the final user of a composed role and
1363             class but are used by the role to excersize the class.
1364              
1365             =head3 _process_the_data( $passed_ref, $conversion_ref )
1366              
1367             =over
1368              
1369             B<Definition:> This method is the gate keeper to the recursive parsing of
1370             Data::Walk::Extracted. This method ensures that the minimum requirements for the recursive
1371             data parser are met. If needed it will use a conversion ref (also provided by the caller) to
1372             change input hash keys to the generic hash keys used by this class. This function then
1373             calls the actual recursive function. For an overview of the recursive steps see the
1374             L<flow outline|/Recursive Parsing Flow>.
1375              
1376             B<Accepts:> ( $passed_ref, $conversion_ref )
1377              
1378             =over
1379              
1380             B<$passed_ref> this ref contains key value pairs as follows;
1381              
1382             =over
1383              
1384             B<primary_ref> - a dataref that the walker will walk - required
1385              
1386             =over
1387              
1388             review the $conversion_ref functionality in this function for renaming of this key.
1389              
1390             =back
1391              
1392             B<secondary_ref> - a dataref that is used for comparision while walking. - optional
1393              
1394             =over
1395              
1396             review the $conversion_ref functionality in this function for renaming of this key.
1397              
1398             =back
1399              
1400             B<before_method> - a method name that will perform some action at the beginning
1401             of each node - optional
1402              
1403             B<after_method> - a method name that will perform some action at the end
1404             of each node - optional
1405              
1406             B<[attribute name]> - L<supported|/Supported one shot attributes> attribute names are
1407             accepted with temporary attribute settings here. These settings are temporarily set for
1408             a single "_process_the_data" call and then the original attribute values are restored.
1409              
1410             =back
1411              
1412             B<$conversion_ref> This allows a public method to accept different key names for the
1413             various keys listed above and then convert them later to the generic terms used by this class.
1414             - optional
1415              
1416             B<Example>
1417              
1418             $passed_ref ={
1419             print_ref =>{
1420             First_key => [
1421             'first_value',
1422             'second_value'
1423             ],
1424             },
1425             match_ref =>{
1426             First_key => 'second_value',
1427             },
1428             before_method => '_print_before_method',
1429             after_method => '_print_after_method',
1430             sorted_nodes =>{ Array => 1 },#One shot attribute setter
1431             }
1432              
1433             $conversion_ref ={
1434             primary_ref => 'print_ref',# generic_name => role_name,
1435             secondary_ref => 'match_ref',
1436             }
1437              
1438             =back
1439              
1440             B<Returns:> the $passed_ref (only) with the key names restored to the ones passed to this
1441             method using the $conversion_ref.
1442              
1443             =back
1444              
1445             =head3 _build_branch( $seed_ref, @arg_list )
1446              
1447             =over
1448              
1449             B<Definition:> There are times when a role will wish to reconstruct the data branch
1450             that lead from the 'zeroth' node to where the data walker is currently at. This private
1451             method takes a seed reference and uses data found in the L<branch ref
1452             |/A position trace is generated> to recursivly append to the front of the seed until a
1453             complete branch to the zeroth node is generated. I<The branch_ref list must be
1454             explicitly passed.>
1455              
1456             B<Accepts:> a list of arguments starting with the $seed_ref to build from.
1457             The remaining arguments are just the array elements of the 'branch ref'.
1458              
1459             B<Example:>
1460              
1461             $ref = $self->_build_branch(
1462             $seed_ref,
1463             @{ $passed_ref->{branch_ref}},
1464             );
1465              
1466             B<Returns:> a data reference with the current path back to the start pre-pended
1467             to the $seed_ref
1468              
1469             =back
1470              
1471             =head3 _extracted_ref_type( $test_ref )
1472              
1473             =over
1474              
1475             B<Definition:> In order to manage data types necessary for this class a data
1476             walker compliant 'Type' tester is provided. This is necessary to support a few non
1477             perl-standard types not generated in standard perl typing systems. First, 'undef'
1478             is the UNDEF type. Second, strings and numbers both return as 'SCALAR' (not '' or undef).
1479             B<Much of the code in this package runs on dispatch tables that are built around these
1480             specific type definitions.>
1481              
1482             B<Accepts:> It receives a $test_ref that can be undef.
1483              
1484             B<Returns:> a data walker type or it confesses.
1485              
1486             =back
1487              
1488             =head3 _get_had_secondary
1489              
1490             =over
1491              
1492             B<Definition:> during the initial processing of data in
1493             L<_process_the_data|/_process_the_data( $passed_ref, $conversion_ref )> the existence
1494             of a passed secondary ref is tested and stored in the attribute '_had_secondary'. On
1495             occasion a role might need to know if a secondary ref existed at any level if it it is
1496             not represented at the current level.
1497              
1498             B<Accepts:> nothing
1499              
1500             B<Returns:> True|1 if the secondary ref ever existed
1501              
1502             =back
1503              
1504             =head3 _get_current_level
1505              
1506             =over
1507              
1508             B<Definition:> on occasion you may need for one of the methods to know what
1509             level is currently being parsed. This will provide that information in integer
1510             format.
1511              
1512             B<Accepts:> nothing
1513              
1514             B<Returns:> the integer value for the level
1515              
1516             =back
1517              
1518             =head2 Public Methods
1519              
1520             =head3 add_sorted_nodes( NODETYPE => 1, )
1521              
1522             =over
1523              
1524             B<Definition:> This method is used to add nodes to be sorted to the walker by
1525             adjusting the attribute L<sorted_nodes|/sorted_nodes>.
1526              
1527             B<Accepts:> Node key => value pairs where the key is the Node name and the value is
1528             1. This method can accept multiple key => value pairs.
1529              
1530             B<Returns:> nothing
1531              
1532             =back
1533              
1534             =head3 has_sorted_nodes
1535              
1536             =over
1537              
1538             B<Definition:> This method checks if any sorting is turned on in the attribute
1539             L<sorted_nodes|/sorted_nodes>.
1540              
1541             B<Accepts:> Nothing
1542              
1543             B<Returns:> the count of sorted node types listed
1544              
1545             =back
1546              
1547             =head3 check_sorted_nodes( NODETYPE )
1548              
1549             =over
1550              
1551             B<Definition:> This method is used to see if a node type is sorted by testing the
1552             attribute L<sorted_nodes|/sorted_nodes>.
1553              
1554             B<Accepts:> the name of one node type
1555              
1556             B<Returns:> true if that node is sorted as determined by L<sorted_nodes|/sorted_nodes>
1557              
1558             =back
1559              
1560             =head3 clear_sorted_nodes
1561              
1562             =over
1563              
1564             B<Definition:> This method will clear all values in the attribute
1565             L<sorted_nodes|/sorted_nodes>. I<and therefore turn off all cleared sorts>.
1566              
1567             B<Accepts:> nothing
1568              
1569             B<Returns:> nothing
1570              
1571             =back
1572              
1573             =head3 remove_sorted_node( NODETYPE1, NODETYPE2, )
1574              
1575             =over
1576              
1577             B<Definition:> This method will clear the key / value pairs in L<sorted_nodes|/sorted_nodes>
1578             for the listed items.
1579              
1580             B<Accepts:> a list of NODETYPES to delete
1581              
1582             B<Returns:> In list context it returns a list of values in the hash for the deleted
1583             keys. In scalar context it returns the value for the last key specified
1584              
1585             =back
1586              
1587             =head3 set_sorted_nodes( $hashref )
1588              
1589             =over
1590              
1591             B<Definition:> This method will completely reset the attribute L<sorted_nodes|/sorted_nodes> to
1592             $hashref.
1593              
1594             B<Accepts:> a hashref of NODETYPE keys with the value of 1.
1595              
1596             B<Returns:> nothing
1597              
1598             =back
1599              
1600             =head3 get_sorted_nodes
1601              
1602             =over
1603              
1604             B<Definition:> This method will return a hashref of the attribute L<sorted_nodes|/sorted_nodes>
1605              
1606             B<Accepts:> nothing
1607              
1608             B<Returns:> a hashref
1609              
1610             =back
1611              
1612             =head3 add_skipped_nodes( NODETYPE1 => 1, NODETYPE2 => 1 )
1613              
1614             =over
1615              
1616             B<Definition:> This method adds additional skip definition(s) to the
1617             L<skipped_nodes|/skipped_nodes> attribute.
1618              
1619             B<Accepts:> a list of key value pairs as used in 'skipped_nodes'
1620              
1621             B<Returns:> nothing
1622              
1623             =back
1624              
1625             =head3 has_skipped_nodes
1626              
1627             =over
1628              
1629             B<Definition:> This method checks if any nodes are set to be skipped in the
1630             attribute L<skipped_nodes|/skipped_nodes>.
1631              
1632             B<Accepts:> Nothing
1633              
1634             B<Returns:> the count of skipped node types listed
1635              
1636             =back
1637              
1638             =head3 check_skipped_node( $string )
1639              
1640             =over
1641              
1642             B<Definition:> This method checks if a specific node type is set to be skipped in
1643             the L<skipped_nodes|/skipped_nodes> attribute.
1644              
1645             B<Accepts:> a string
1646              
1647             B<Returns:> Boolean value indicating if the specific $string is set
1648              
1649             =back
1650              
1651             =head3 remove_skipped_nodes( NODETYPE1, NODETYPE2 )
1652              
1653             =over
1654              
1655             B<Definition:> This method deletes specificily identified node skips from the
1656             L<skipped_nodes|/skipped_nodes> attribute.
1657              
1658             B<Accepts:> a list of NODETYPES to delete
1659              
1660             B<Returns:> In list context it returns a list of values in the hash for the deleted
1661             keys. In scalar context it returns the value for the last key specified
1662              
1663             =back
1664              
1665             =head3 clear_skipped_nodes
1666              
1667             =over
1668              
1669             B<Definition:> This method clears all data in the L<skipped_nodes|/skipped_nodes> attribute.
1670              
1671             B<Accepts:> nothing
1672              
1673             B<Returns:> nothing
1674              
1675             =back
1676              
1677             =head3 set_skipped_nodes( $hashref )
1678              
1679             =over
1680              
1681             B<Definition:> This method will completely reset the attribute L<skipped_nodes|/skipped_nodes> to
1682             $hashref.
1683              
1684             B<Accepts:> a hashref of NODETYPE keys with the value of 1.
1685              
1686             B<Returns:> nothing
1687              
1688             =back
1689              
1690             =head3 get_skipped_nodes
1691              
1692             =over
1693              
1694             B<Definition:> This method will return a hashref of the attribute L<skipped_nodes|/skipped_nodes>
1695              
1696             B<Accepts:> nothing
1697              
1698             B<Returns:> a hashref
1699              
1700             =back
1701              
1702             =head3 set_skip_level( $int )
1703              
1704             =over
1705              
1706             B<Definition:> This method is used to reset the L<skip_level|/skip_level>
1707             attribute after the instance is created.
1708              
1709             B<Accepts:> an integer (negative numbers and 0 will be ignored)
1710              
1711             B<Returns:> nothing
1712              
1713             =back
1714              
1715             =head3 get_skip_level()
1716              
1717             =over
1718              
1719             B<Definition:> This method returns the current L<skip_level|/skip_level>
1720             attribute.
1721              
1722             B<Accepts:> nothing
1723              
1724             B<Returns:> an integer
1725              
1726             =back
1727              
1728             =head3 has_skip_level()
1729              
1730             =over
1731              
1732             B<Definition:> This method is used to test if the L<skip_level|/skip_level> attribute is set.
1733              
1734             B<Accepts:> nothing
1735              
1736             B<Returns:> $Bool value indicating if the 'skip_level' attribute has been set
1737              
1738             =back
1739              
1740             =head3 clear_skip_level()
1741              
1742             =over
1743              
1744             B<Definition:> This method clears the L<skip_level|/skip_level> attribute.
1745              
1746             B<Accepts:> nothing
1747              
1748             B<Returns:> nothing (always successful)
1749              
1750             =back
1751              
1752             =head3 set_skip_node_tests( ArrayRef[ArrayRef] )
1753              
1754             =over
1755              
1756             B<Definition:> This method is used to change (completly) the 'skip_node_tests'
1757             attribute after the instance is created. See L<skip_node_tests|/skip_node_tests> for an example.
1758              
1759             B<Accepts:> an array ref of array refs
1760              
1761             B<Returns:> nothing
1762              
1763             =back
1764              
1765             =head3 get_skip_node_tests()
1766              
1767             =over
1768              
1769             B<Definition:> This method returns the current master list from the
1770             L<skip_node_tests|/skip_node_tests> attribute.
1771              
1772             B<Accepts:> nothing
1773              
1774             B<Returns:> an array ref of array refs
1775              
1776             =back
1777              
1778             =head3 has_skip_node_tests()
1779              
1780             =over
1781              
1782             B<Definition:> This method is used to test if the L<skip_node_tests|/skip_node_tests> attribute
1783             is set.
1784              
1785             B<Accepts:> nothing
1786              
1787             B<Returns:> The number of sub array refs there are in the list
1788              
1789             =back
1790              
1791             =head3 clear_skip_node_tests()
1792              
1793             =over
1794              
1795             B<Definition:> This method clears the L<skip_node_tests|/skip_node_tests> attribute.
1796              
1797             B<Accepts:> nothing
1798              
1799             B<Returns:> nothing (always successful)
1800              
1801             =back
1802              
1803             =head3 add_skip_node_tests( ArrayRef1, ArrayRef2 )
1804              
1805             =over
1806              
1807             B<Definition:> This method adds additional skip_node_test definition(s) to the the
1808             L<skip_node_tests|/skip_node_tests> attribute list.
1809              
1810             B<Accepts:> a list of array refs as used in 'skip_node_tests'. These are 'pushed
1811             onto the existing list.
1812              
1813             B<Returns:> nothing
1814              
1815             =back
1816              
1817             =head3 set_change_array_size( $bool )
1818              
1819             =over
1820              
1821             B<Definition:> This method is used to (re)set the L<change_array_size|/change_array_size> attribute
1822             after the instance is created.
1823              
1824             B<Accepts:> a Boolean value
1825              
1826             B<Returns:> nothing
1827              
1828             =back
1829              
1830             =head3 get_change_array_size()
1831              
1832             =over
1833              
1834             B<Definition:> This method returns the current state of the L<change_array_size|/change_array_size>
1835             attribute.
1836              
1837             B<Accepts:> nothing
1838              
1839             B<Returns:> $Bool value representing the state of the 'change_array_size'
1840             attribute
1841              
1842             =back
1843              
1844             =head3 has_change_array_size()
1845              
1846             =over
1847              
1848             B<Definition:> This method is used to test if the L<change_array_size|/change_array_size>
1849             attribute is set.
1850              
1851             B<Accepts:> nothing
1852              
1853             B<Returns:> $Bool value indicating if the 'change_array_size' attribute
1854             has been set
1855              
1856             =back
1857              
1858             =head3 clear_change_array_size()
1859              
1860             =over
1861              
1862             B<Definition:> This method clears the L<change_array_size|/change_array_size> attribute.
1863              
1864             B<Accepts:> nothing
1865              
1866             B<Returns:> nothing
1867              
1868             =back
1869              
1870             =head3 set_fixed_primary( $bool )
1871              
1872             =over
1873              
1874             B<Definition:> This method is used to change the L<fixed_primary|/fixed_primary> attribute
1875             after the instance is created.
1876              
1877             B<Accepts:> a Boolean value
1878              
1879             B<Returns:> nothing
1880              
1881             =back
1882              
1883             =head3 get_fixed_primary()
1884              
1885             =over
1886              
1887             B<Definition:> This method returns the current state of the L<fixed_primary|/fixed_primary>
1888             attribute.
1889              
1890             B<Accepts:> nothing
1891              
1892             B<Returns:> $Bool value representing the state of the 'fixed_primary' attribute
1893              
1894             =back
1895              
1896             =head3 has_fixed_primary()
1897              
1898             =over
1899              
1900             B<Definition:> This method is used to test if the L<fixed_primary|/fixed_primary> attribute is set.
1901              
1902             B<Accepts:> nothing
1903              
1904             B<Returns:> $Bool value indicating if the 'fixed_primary' attribute has been set
1905              
1906             =back
1907              
1908             =head3 clear_fixed_primary()
1909              
1910             =over
1911              
1912             B<Definition:> This method clears the L<fixed_primary|/fixed_primary> attribute.
1913              
1914             B<Accepts:> nothing
1915              
1916             B<Returns:> nothing
1917              
1918             =back
1919              
1920             =head1 Definitions
1921              
1922             =head2 node
1923              
1924             Each branch point of a data reference is considered a node. The possible paths
1925             deeper into the data structure from the node are followed 'vertically first' in
1926             recursive parsing. The original top level reference is considered the 'zeroth'
1927             node.
1928              
1929             =head2 base node type
1930              
1931             Recursion 'base' node L<types|/_extracted_ref_type( $test_ref )> are considered
1932             to not have any possible deeper branches. Currently that list is SCALAR and UNDEF.
1933              
1934             =head2 Supported node walking types
1935              
1936             =over
1937              
1938             =item ARRAY
1939              
1940             =item HASH
1941              
1942             =item SCALAR
1943              
1944             =item UNDEF
1945              
1946             I<Other node support>
1947              
1948             Support for Objects is partially implemented and as a consequence '_process_the_data'
1949             won't immediatly die when asked to parse an object. It will still die but on a
1950             dispatch table call that indicates where there is missing object support, not at the
1951             top of the node. This allows for some of the L<skip attributes|/skipped_nodes> to
1952             use 'OBJECT' in their definitions.
1953              
1954             =back
1955              
1956             =head2 Supported one shot attributes
1957              
1958             L<explanation|/Attributes>
1959              
1960             =over
1961              
1962             =item sorted_nodes
1963              
1964             =item skipped_nodes
1965              
1966             =item skip_level
1967              
1968             =item skip_node_tests
1969              
1970             =item change_array_size
1971              
1972             =item fixed_primary
1973              
1974             =back
1975              
1976             =head2 Dispatch Tables
1977              
1978             This class uses the role L<Data::Walk::Extracted::Dispatch
1979             |https://metacpan.org/module/Data::Walk::Extracted::Dispatch> to implement dispatch
1980             tables. When there is a decision point, that role is used to make the class
1981             extensible.
1982              
1983             =head1 Caveat utilitor
1984              
1985             This is not an extention of L<Data::Walk|https://metacpan.org/module/Data::Walk>
1986              
1987             The core class has no external effect. All output comes from
1988             L<additions to the class|/Extending Data::Walk::Extracted>.
1989              
1990             This module uses the 'L<defined or|http://perldoc.perl.org/perlop.html#Logical-Defined-Or>'
1991             ( //= ) and so requires perl 5.010 or higher.
1992              
1993             This is a L<Moose|https://metacpan.org/module/Moose::Manual> based data handling class.
1994             Many coders will tell you Moose and data manipulation don't belong together. They are
1995             most certainly right in speed intensive circumstances.
1996              
1997             Recursive parsing is not a good fit for all data since very deep data structures will
1998             fill up a fair amount of memory! Meaning that as the module recursively parses through
1999             the levels it leaves behind snapshots of the previous level that allow it to keep
2000             track of it's location.
2001              
2002             The passed data references are effectivly deep cloned during this process. To leave
2003             the primary_ref pointer intact see L<fixed_primary|/fixed_primary>
2004              
2005             =head1 GLOBAL VARIABLES
2006              
2007             =over
2008              
2009             B<$ENV{Smart_Comments}>
2010              
2011             The module uses L<Smart::Comments|https://metacpan.org/module/Smart::Comments> if the '-ENV'
2012             option is set. The 'use' is encapsulated in an if block triggered by an environmental
2013             variable to comfort non-believers. Setting the variable $ENV{Smart_Comments} in a BEGIN
2014             block will load and turn on smart comment reporting. There are three levels of 'Smartness'
2015             available in this module '###', '####', and '#####'.
2016              
2017             =back
2018              
2019             =head1 Build/Install from Source
2020              
2021             B<1.> Download a compressed file with the code
2022              
2023             B<2.> Extract the code from the compressed file. If you are using tar this should work:
2024              
2025             tar -zxvf Data-Walk-Extracted-v0.xx.xx.tar.gz
2026              
2027             B<3.> Change (cd) into the extracted directory
2028              
2029             B<4.> Run the following commands
2030              
2031             =over
2032              
2033             (For Windows find what version of make was used to compile your perl)
2034              
2035             perl -V:make
2036              
2037             (then for Windows substitute the correct make function (ex. s/make/dmake/g))
2038              
2039             =back
2040              
2041             >perl Makefile.PL
2042              
2043             >make
2044              
2045             >make test
2046              
2047             >make install # As sudo/root
2048              
2049             >make clean
2050              
2051             =head1 SUPPORT
2052              
2053             =over
2054              
2055             L<github Data-Walk-Extracted/issues|https://github.com/jandrew/Data-Walk-Extracted/issues>
2056              
2057             =back
2058              
2059             =head1 TODO
2060              
2061             =over
2062              
2063             B<1.> provide full recursion through Objects
2064              
2065             B<2.> Support recursion through CodeRefs (Closures)
2066              
2067             B<3.> Add a Data::Walk::Diff Role to the package
2068              
2069             B<4.> Add a Data::Walk::Top Role to the package
2070              
2071             B<5.> Add a Data::Walk::Thin Role to the package
2072              
2073             B<6.> Add a Data::Walk::Substitute Role to the package
2074              
2075             B<7.> Add L<Log::Shiras|https://metacpan.org/module/Log::Shiras> debugging in exchange for
2076             L<Smart::Comments|https://metacpan.org/module/Smart::Comments>
2077              
2078             =back
2079              
2080             =head1 AUTHOR
2081              
2082             =over
2083              
2084             =item Jed Lund
2085              
2086             =item jandrew@cpan.org
2087              
2088             =back
2089              
2090             =head1 COPYRIGHT
2091              
2092             This program is free software; you can redistribute
2093             it and/or modify it under the same terms as Perl itself.
2094              
2095             The full text of the license can be found in the
2096             LICENSE file included with this module.
2097              
2098             This software is copyrighted (c) 2013 by Jed Lund.
2099              
2100             =head1 Dependencies
2101              
2102             =over
2103              
2104             L<version>
2105              
2106             L<5.010|http://perldoc.perl.org/perl5100delta.html> (for use of
2107             L<defined or|http://perldoc.perl.org/perlop.html#Logical-Defined-Or> //)
2108              
2109             L<Class::Inspector>
2110              
2111             L<Scalar::Util>
2112              
2113             L<Carp>
2114              
2115             L<Moose>
2116              
2117             L<MooseX::StrictConstructor>
2118              
2119             L<MooseX::Types::Moose>
2120              
2121             L<Data::Walk::Extracted::Types>
2122              
2123             L<Data::Walk::Extracted::Dispatch>
2124              
2125             =back
2126              
2127             =head1 SEE ALSO
2128              
2129             =over
2130              
2131             L<Smart::Comments> - is used if the -ENV option is set
2132              
2133             L<Data::Walk>
2134              
2135             L<Data::Walker>
2136              
2137             L<Data::Dumper> - Dumper
2138              
2139             L<YAML> - Dump
2140              
2141             L<Data::Walk::Print> - available Data::Walk::Extracted Role
2142              
2143             L<Data::Walk::Prune> - available Data::Walk::Extracted Role
2144              
2145             L<Data::Walk::Graft> - available Data::Walk::Extracted Role
2146              
2147             L<Data::Walk::Clone> - available Data::Walk::Extracted Role
2148              
2149             =back
2150              
2151             =cut
2152              
2153             #########1 Main POD ends 3#########4#########5#########6#########7#########8#########9