File Coverage

blib/lib/Data/Walk/Extracted.pm
Criterion Covered Total %
statement 225 259 86.8
branch 76 104 73.0
condition 22 40 55.0
subroutine 37 39 94.8
pod n/a
total 360 442 81.4


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