File Coverage

blib/lib/Data/Walk/Clone.pm
Criterion Covered Total %
statement 32 36 88.8
branch 8 10 80.0
condition 4 6 66.6
subroutine 8 9 88.8
pod 2 2 100.0
total 54 63 85.7


line stmt bran cond sub pod time code
1             package Data::Walk::Clone;
2             our $AUTHORITY = 'cpan:JANDREW';
3 3     3   5885 use version; our $VERSION = version->declare('v0.26.16');
  3         3  
  3         16  
4 3     3   248 use Moose::Role;
  3         3  
  3         18  
5             requires
6             '_process_the_data',
7             '_dispatch_method',
8             '_get_had_secondary';
9 3         24 use Types::Standard qw(
10             HashRef
11             is_HashRef
12             Bool
13 3     3   10222 );
  3         3  
14             if( $ENV{ Smart_Comments } ){
15 3     3   1780 use Smart::Comments -ENV;
  3         4  
  3         20  
16             ### Smart-Comments turned on for Data-Walk-Clone
17             }
18              
19             #########1 Package Variables 3#########4#########5#########6#########7#########8#########9
20              
21             $| = 1;
22             my $clone_keys = {
23             donor_ref => 'primary_ref',
24             };
25              
26             #########1 Dispatch Tables 3#########4#########5#########6#########7#########8#########9
27              
28             my $seed_clone_dispatch ={######<------------------------------------ ADD New types here
29             ARRAY => sub{
30             unless( exists $_[1]->{secondary_ref} ){
31             $_[1]->{secondary_ref} = [];
32             }
33             return $_[1];
34             },
35             HASH => sub{
36             unless( exists $_[1]->{secondary_ref} ){
37             $_[1]->{secondary_ref} = {};
38             }
39             return $_[1];
40             },
41             OBJECT => sub{
42             unless( exists $_[1]->{secondary_ref} ){
43             $_[1]->{secondary_ref} = bless( {}, ref $_[1]->{primary_ref} );
44             }
45             return $_[1];
46             },
47             SCALAR => sub{
48             $_[1]->{secondary_ref} = $_[1]->{primary_ref};
49             return $_[1];
50             },
51             name => 'seed_clone_dispatch',#Meta data
52             };
53              
54             #########1 Public Attributes 3#########4#########5#########6#########7#########8#########9
55              
56             has 'should_clone' =>(
57             is => 'ro',
58             isa => Bool,
59             writer => 'set_should_clone',
60             reader => 'get_should_clone',
61             predicate => 'has_should_clone',
62             default => 1,
63             );
64              
65             sub clear_should_clone{
66             ### <where> - turn cloning back on at clear_should_clone ...
67 0     0 1 0 my ( $self, ) = @_;
68 0         0 $self->set_should_clone( 1 );
69 0         0 return 1;
70             }
71              
72             #########1 Public Methods 3#########4#########5#########6#########7#########8#########9
73              
74             sub deep_clone{#Used to convert names for Data::Walk:Extracted
75             ### <where> - Made it to deep_clone
76             ##### <where> - Passed input : @_
77 23     23 1 2973 my $self = $_[0];
78             my $passed_ref =
79             ( @_ == 2 ) ?
80 23 50 66     101 ( ( is_HashRef( $_[1] ) and exists $_[1]->{donor_ref} ) ?
    100          
81             $_[1] : { donor_ref => $_[1] } ) :
82             { @_[1 .. $#_] } ;
83             ##### <where> - Passed hashref: $passed_ref
84             @$passed_ref{
85 23         43 'before_method', 'after_method',
86             } = (
87             '_clone_before_method', '_clone_after_method',
88             );
89             ##### <where> - Start recursive parsing with : $passed_ref
90 23         73 $passed_ref = $self->_process_the_data( $passed_ref, $clone_keys );
91 23         547 $self->_set_first_pass( 1 );# Re-set
92             ### <where> - End recursive parsing with : $passed_ref
93 23         88 return $passed_ref->{secondary_ref};
94             }
95              
96             #########1 Private Attributes 3#########4#########5#########6#########7#########8#########9
97              
98             has '_first_pass' =>(
99             is => 'ro',
100             isa => Bool,
101             writer => '_set_first_pass',
102             reader => '_get_first_pass',
103             default => 1,
104             );
105              
106             #########1 Private Methods 3#########4#########5#########6#########7#########8#########9
107              
108             sub _clone_before_method{
109 103     103   81 my ( $self, $passed_ref ) = @_;
110             ### <where> - reached _clone_before_method
111             #### <where> - received input: $passed_ref
112             ### <where> - doner_ref: $passed_ref->{primary_ref}
113             ##### <where> - self: $self
114 103 100       2565 if( $self->_get_first_pass ){
115             ### <where> perform a one time test for should_clone ...
116 23 50       591 if( !$self->get_should_clone ){
117             ### <where> - skipping level now ...
118 0         0 $passed_ref->{skip} = 'YES';
119             }else{
120             ### <where> - turn on one element of cloning ...
121 23         618 $self->_set_had_secondary( 1 );
122             }
123 23         595 $self->_set_first_pass( 0 );
124             }
125 103         162 return $passed_ref;
126             }
127              
128             sub _clone_after_method{
129 103     103   77 my ( $self, $passed_ref ) = @_;
130             ### <where> - reached _clone_after_method
131             #### <where> - received input: $passed_ref
132             ### <where> - current item: $passed_ref->{branch_ref}->[-1]
133             ### <where> - should clone?: $self->get_should_clone
134 103 100 66     2534 if( $self->get_should_clone and
135             $passed_ref->{skip} eq 'NO' ){
136             ### <where> - seeding the clone as needed for: $passed_ref->{primary_type}
137             $passed_ref = $self->_dispatch_method(
138             $seed_clone_dispatch,
139             $passed_ref->{primary_type},
140 94         178 $passed_ref,
141             );
142             }else{
143             # Eliminating the clone at this level
144 9         14 $passed_ref->{secondary_ref} = $passed_ref->{primary_ref};
145             }
146             #### <where> - the new passed_ref is: $passed_ref
147 103         153 return $passed_ref;
148             }
149              
150             #########1 Phinish Strong 3#########4#########5#########6#########7#########8#########9
151              
152 3     3   3013 no Moose::Role;
  3         3  
  3         16  
153              
154             1;
155             # The preceding line will help the module return a true value
156              
157             #########1 Main POD starts 3#########4#########5#########6#########7#########8#########9
158              
159             __END__
160              
161             =head1 NAME
162              
163             Data::Walk::Clone - deep data cloning with boundaries
164              
165             =head1 SYNOPSIS
166              
167             #!perl
168             use Moose::Util qw( with_traits );
169             use Data::Walk::Extracted;
170             use Data::Walk::Clone;
171              
172             my $dr_nisar_ahmad_wani = with_traits(
173             'Data::Walk::Extracted',
174             ( 'Data::Walk::Clone', )
175             )->new(
176             skip_node_tests =>[ [ 'HASH', 'LowerKey2', 'ALL', 'ALL' ] ],
177             );
178             my $donor_ref = {
179             Someotherkey => 'value',
180             Parsing =>{
181             HashRef =>{
182             LOGGER =>{
183             run => 'INFO',
184             },
185             },
186             },
187             Helping =>[
188             'Somelevel',
189             {
190             MyKey =>{
191             MiddleKey =>{
192             LowerKey1 => 'lvalue1',
193             LowerKey2 => {
194             BottomKey1 => 'bvalue1',
195             BottomKey2 => 'bvalue2',
196             },
197             },
198             },
199             },
200             ],
201             };
202             my $injaz_ref = $dr_nisar_ahmad_wani->deep_clone(
203             donor_ref => $donor_ref,
204             );
205             if(
206             $injaz_ref->{Helping}->[1]->{MyKey}->{MiddleKey}->{LowerKey2} eq
207             $donor_ref->{Helping}->[1]->{MyKey}->{MiddleKey}->{LowerKey2} ){
208             print "The data is not cloned at the skip point\n";
209             }
210              
211             if(
212             $injaz_ref->{Helping}->[1]->{MyKey}->{MiddleKey} ne
213             $donor_ref->{Helping}->[1]->{MyKey}->{MiddleKey} ){
214             print "The data is cloned above the skip point\n";
215             }
216              
217             #####################################################################################
218             # Output of SYNOPSIS
219             # 01 The data is not cloned at the skip point
220             # 02 The data is cloned above the skip point
221             #####################################################################################
222              
223             =head1 DESCRIPTION
224              
225             This L<Moose::Role|https://metacpan.org/module/Moose::Manual::Roles> contains
226             methods for implementing the method L<deep_clone|/deep_clone( $arg_ref|%args|$data_ref )> using
227             L<Data::Walk::Extracted|https://metacpan.org/module/Data::Walk::Extracted>.
228             This method is used to deep clone (clone many/all) levels of a data ref. Deep cloning
229             is accomplished by sending a 'donor_ref' that has data nodes that you want copied into a
230             different memory location. In general Data::Walk::Extracted already deep clones any
231             output as part of its data walking so the primary value of this role is to manage
232             deep cloning boundaries. It may be that some portion of the data should maintain common
233             memory references to the original memory references and so all of the Data::Walk::Extracted
234             skip methods will be recognized and supported. Meaning that if a node is skipped the
235             data reference will be copied directly rather than cloned. The deep clone boundaries
236             are managed using the L<skip attributes
237             |https://metacpan.org/module/Data::Walk::Extracted#skipped_nodes> in Data::Walk::Extracted.
238              
239             =head2 USE
240              
241             This is a L<Moose::Role|https://metacpan.org/module/Moose::Manual::Roles> specifically
242             designed to be used with L<Data::Walk::Extracted
243             |https://metacpan.org/module/Data::Walk::Extracted#Extending-Data::Walk::Extracted>.
244             It can be combined traditionaly to the ~::Extracted class using L<Moose
245             |https://metacpan.org/module/Moose::Manual::Roles> methods or for information on how to join
246             this role to Data::Walk::Extracted at run time see L<Moose::Util
247             |https://metacpan.org/module/Moose::Util> or L<MooseX::ShortCut::BuildInstance
248             |https://metacpan.org/module/MooseX::ShortCut::BuildInstance> for more information.
249              
250             =head1 Attributes
251              
252             Data passed to -E<gt>new when creating an instance. For modification of these attributes
253             see L<Methods|/Methods>. The -E<gt>new function will either accept fat comma lists or a
254             complete hash ref that has the possible attributes as the top keys. Additionally
255             some attributes that have all the following methods; get_$attribute, set_$attribute,
256             has_$attribute, and clear_$attribute, can be passed to L<deep_clone
257             |/deep_clone( $arg_ref|%args|$data_ref )> and will be adjusted for just the run of that
258             method call. These are called 'one shot' attributes. The class and each role (where
259             applicable) in this package have a list of 'supported one shot attributes'.
260              
261             =head2 should_clone
262              
263             =over
264              
265             B<Definition:> There are times when the cloning needs to be turned off. This
266             is the switch. If this is set to 0 then deep_clone just passes the doner ref back.
267              
268             B<Default> undefined = everything is cloned
269              
270             B<Range> Boolean values (0|1)
271              
272             =back
273              
274             =head2 (see also)
275              
276             L<Data::Walk::Extracted|https://metacpan.org/module/Data::Walk::Extracted#Attributes>
277             Attributes
278              
279             =head1 Methods
280              
281             =head2 deep_clone( $arg_ref|%args|$data_ref )
282              
283             =over
284              
285             B<Definition:> This takes a 'donor_ref' and deep clones it.
286              
287             B<Accepts:> either a single data reference or named arguments
288             in a fat comma list or hashref
289              
290             =over
291              
292             B<Hash option> - if data comes in a fat comma list or as a hash ref
293             and the keys include a 'donor_ref' key then the list is processed as such.
294              
295             =over
296              
297             B<donor_ref> - this is the data reference that should be deep cloned - required
298              
299             B<[attribute name]> - attribute names are accepted with temporary attribute
300             settings. These settings are temporarily set for a single "deep_clone" call and
301             then the original attribute values are restored. For this to work the the attribute
302             must meet the L<necessary criteria|/Attributes>.
303              
304             =back
305              
306             B<single data reference option> - if only one data_ref is sent and it fails
307             the test;
308              
309             exists $data_ref->{donor_ref}
310              
311             then the program will attempt to name it as donor_ref => $data_ref and then clone
312             the whole thing.
313              
314             =back
315              
316             B<Returns:> The deep cloned data reference
317              
318             =back
319              
320             =head2 get_should_clone
321              
322             =over
323              
324             B<Definition:> This will get the current value of the attribute
325             L<should_clone|/should_clone>
326              
327             B<Accepts:> nothing
328              
329             B<Returns:> a boolean value
330              
331             =back
332              
333             =head2 set_should_clone( $Bool )
334              
335             =over
336              
337             B<Definition:> This will set the attribute L<should_clone|/should_clone>
338              
339             B<Accepts:> a boolean value
340              
341             B<Returns:> nothing
342              
343             =back
344              
345             =head2 has_should_clone
346              
347             =over
348              
349             B<Definition:> This will return true if the attribute L<should_clone|/should_clone>
350             is active
351              
352             B<Accepts:> nothing
353              
354             B<Returns:> a boolean value
355              
356             =back
357              
358             =head2 clear_should_clone
359              
360             =over
361              
362             B<Definition:> This will set the attribute L<should_clone|/should_clone>
363             to one ( 1 ). I<The name is awkward to accomodate one shot attribute changes.>
364              
365             B<Accepts:> nothing
366              
367             B<Returns:> nothing
368              
369             =back
370              
371             =head1 Caveat utilitor
372              
373             =head2 Supported Node types
374              
375             =over
376              
377             =item ARRAY
378              
379             =item HASH
380              
381             =item SCALAR
382              
383             =back
384              
385             =head1 GLOBAL VARIABLES
386              
387             =over
388              
389             B<$ENV{Smart_Comments}>
390              
391             The module uses L<Smart::Comments|https://metacpan.org/module/Smart::Comments> if the '-ENV'
392             option is set. The 'use' is encapsulated in an if block triggered by an environmental
393             variable to comfort non-believers. Setting the variable $ENV{Smart_Comments} in a BEGIN
394             block will load and turn on smart comment reporting. There are three levels of 'Smartness'
395             available in this module '###', '####', and '#####'.
396              
397             =back
398              
399             =head1 SUPPORT
400              
401             =over
402              
403             L<github Data-Walk-Extracted/issues|https://github.com/jandrew/Data-Walk-Extracted/issues>
404              
405             =back
406              
407             =head1 TODO
408              
409             =over
410              
411             B<1.> Add L<Log::Shiras|https://metacpan.org/module/Log::Shiras> debugging in exchange for
412             L<Smart::Comments|https://metacpan.org/module/Smart::Comments>
413              
414             B<2.> Support cloning through class instance nodes (can should you even do this?)
415              
416             B<3.> Support cloning through CodeRef nodes
417              
418             B<4.> Support cloning through REF nodes
419              
420             =back
421              
422             =head1 AUTHOR
423              
424             =over
425              
426             =item Jed Lund
427              
428             =item jandrew@cpan.org
429              
430             =back
431              
432             =head1 COPYRIGHT
433              
434             This program is free software; you can redistribute
435             it and/or modify it under the same terms as Perl itself.
436              
437             The full text of the license can be found in the
438             LICENSE file included with this module.
439              
440             This software is copyrighted (c) 2013 by Jed Lund.
441              
442             =head1 Dependencies
443              
444             =over
445              
446             L<version|https://metacpan.org/module/version>
447              
448             L<Moose::Role|https://metacpan.org/module/Moose::Role>
449              
450             =over
451              
452             B<requires>
453              
454             =over
455              
456             =item _process_the_data
457              
458             =item _dispatch_method
459              
460             =item _get_had_secondary
461              
462             =back
463              
464             =back
465              
466             L<MooseX::Types::Moose|https://metacpan.org/module/MooseX::Types::Moose>
467              
468             L<Data::Walk::Extracted|https://metacpan.org/module/Data::Walk::Extracted>
469              
470             L<Data::Walk::Extracted::Dispatch|https://metacpan.org/module/Data::Walk::Extracted::Dispatch>
471              
472             =back
473              
474             =head1 SEE ALSO
475              
476             =over
477              
478             L<Smart::Comments|https://metacpan.org/module/Smart::Comments> - is used if the -ENV option is set
479              
480             L<Data::Walk|https://metacpan.org/module/Data::Walk>
481              
482             L<Data::Walker|https://metacpan.org/module/Data::Walker>
483              
484             L<Storable|https://metacpan.org/module/Storable> - dclone
485              
486             L<Data::Walk::Print|https://metacpan.org/module/Data::Walk::Print> - available Data::Walk::Extracted Role
487              
488             L<Data::Walk::Graft|https://metacpan.org/module/Data::Walk::Graft> - available Data::Walk::Extracted Role
489              
490             L<Data::Walk::Prune|https://metacpan.org/module/Data::Walk::Prune> - available Data::Walk::Extracted Role
491              
492             =back
493              
494             =cut
495              
496             #########1 Main POD ends 3#########4#########5#########6#########7#########8#########9