File Coverage

blib/lib/Tree/MultiNode/Node.pm
Criterion Covered Total %
statement 100 109 91.7
branch 13 18 72.2
condition 1 3 33.3
subroutine 21 22 95.4
pod 13 13 100.0
total 148 165 89.7


line stmt bran cond sub pod time code
1             package Tree::MultiNode::Node;
2 17     17   102 use strict;
  17         39  
  17         474  
3 17     17   62 use warnings;
  17         22  
  17         659  
4 17     17   89 use Carp;
  17         49  
  17         1121  
5 17     17   98 use Scalar::Util qw(weaken);
  17         43  
  17         1432  
6              
7             our $VERSION = '2.02';
8              
9             sub _debug {
10 367 50   367   643 return unless $Tree::MultiNode::debug;
11 17     17   90 no warnings 'uninitialized';
  17         46  
  17         14253  
12 0         0 print @_;
13             }
14              
15             =head1 NAME
16              
17             Tree::MultiNode::Node -- a node in a Tree::MultiNode tree.
18              
19             =head1 DESCRIPTION
20              
21             Please note that the Node object is used internally by the MultiNode object.
22             Though you have the ability to interact with the nodes, it is unlikely that
23             you should need to. That being said, the interface is documented here anyway.
24              
25             =head2 Tree::MultiNode::Node::new
26              
27             new($)
28             @param package name or node object to clone [scalar]
29             @returns new node object
30              
31             new($$)
32             @param key [scalar]
33             @param value [scalar]
34             @returns new node object
35              
36             Creates a new Node. There are three behaviors for new. A constructor with no
37             arguments creates a new, empty node. A single argument of another node object
38             will create a clone of the node object. If two arguments are passed, the first
39             is stored as the key, and the second is stored as the value.
40              
41             # clone an existing node
42             my $node = Tree::MultiNode::Node->new($oldNode);
43             # or
44             my $node = $oldNode->new();
45              
46             # create a new node
47             my $node = Tree::MultiNode::Node->new;
48             my $node = Tree::MultiNode::Node->new("fname");
49             my $node = Tree::MultiNode::Node->new("fname","Larry");
50              
51             =cut
52              
53             sub new {
54 301     301 1 477636 my $this = shift;
55 301   33     758 my $class = ref($this) || $this;
56 301         316 my $self = {};
57 301         404 bless $self, $class;
58              
59 301         353 my $node = shift;
60 301 100       523 if ( ref($node) eq "Tree::MultiNode::Node" ) {
61              
62             # become a copy of that node...
63 14         23 $self->_clone($node);
64             }
65             else {
66 287         343 my ( $key, $value );
67 287         346 $key = $node;
68 287         343 $value = shift;
69 287         586 _debug(__PACKAGE__, "::new() key,val = ", $key, ",", $value, "\n");
70 287         529 $self->{'children'} = [];
71 287         395 $self->{'parent'} = undef;
72 287 100       537 $self->{'key'} = defined $key ? $key : undef;
73 287 100       563 $self->{'value'} = defined $value ? $value : undef;
74             }
75              
76 301         634 return $self;
77             }
78              
79             #
80             # internal method for making the current node a clone of another
81             # node...
82             #
83             sub _clone {
84 14     14   15 my $self = shift;
85 14         15 my $them = shift;
86 14         23 $self->{'parent'} = $them->parent;
87 14 100       39 weaken($self->{'parent'}) if defined $self->{'parent'};
88 14         21 $self->{'key'} = $them->key;
89 14         22 $self->{'value'} = $them->value;
90             # Deep clone children so the copy is fully independent
91 14         19 $self->{'children'} = [];
92 14         16 foreach my $child ( @{$them->children} ) {
  14         22  
93 8         30 my $copy = Tree::MultiNode::Node->new($child);
94 8         14 $copy->{'parent'} = $self;
95 8         19 weaken($copy->{'parent'});
96 8         8 push @{$self->{'children'}}, $copy;
  8         20  
97             }
98             }
99              
100             =head2 Tree::MultiNode::Node::key
101              
102             @param key [scalar]
103             @returns the key [scalar]
104              
105             Used to set, or retrieve the key for a node. If a parameter is passed,
106             it sets the key for the node. The value of the key member is always
107             returned.
108              
109             print $node3->key(), "\n"; # 'fname'
110              
111             =cut
112              
113             sub key {
114 243     243 1 5870 my ( $self, $key ) = @_;
115              
116 243 100       572 if ( @_ > 1 ) {
117 67         152 _debug(__PACKAGE__, "::key() setting key: ", $key, " on ", $self, "\n");
118 67         95 $self->{'key'} = $key;
119             }
120              
121 243         695 return $self->{'key'};
122             }
123              
124             =head2 Tree::MultiNode::Node::value
125              
126             @param the value to set [scalar]
127             @returns the value [scalar]
128              
129             Used to set, or retrieve the value for a node. If a parameter is passed,
130             it sets the value for the node (including undef and other falsy values like
131             0 or ""). The value of the value member is always returned.
132              
133             print $node3->value(), "\n"; # 'Larry'
134             $node3->value(0); # sets value to 0
135             $node3->value(undef); # sets value to undef
136              
137             =cut
138              
139             sub value {
140 90     90 1 1068 my ( $self, $value ) = @_;
141              
142 90 100       275 if ( @_ > 1 ) {
143 13         43 _debug(__PACKAGE__, "::value() setting value: ", $value, " on ", $self, "\n");
144 13         25 $self->{'value'} = $value;
145             }
146              
147 90         312 return $self->{'value'};
148             }
149              
150             =head2 Tree::MultiNode::Node::clear_key
151              
152             @returns the deleted key
153              
154             Clears the key member by deleting it.
155              
156             $node3->clear_key();
157              
158             =cut
159              
160             sub clear_key {
161 1     1 1 5 my $self = shift;
162 1         3 return delete $self->{'key'};
163             }
164              
165             =head2 Tree::MultiNode::Node::clear_value
166              
167             @returns the deleted value
168              
169             Clears the value member by deleting it.
170              
171             $node3->clear_value();
172              
173             =cut
174              
175             sub clear_value {
176 1     1 1 4 my $self = shift;
177 1         3 return delete $self->{'value'};
178             }
179              
180             =head2 Tree::MultiNode::Node::children
181              
182             @returns reference to children [array reference]
183              
184             Returns a reference to the array that contains the children of the
185             node object.
186              
187             $array_ref = $node3->children();
188              
189             =cut
190              
191             sub children {
192 690     690 1 781 my $self = shift;
193 690         1449 return $self->{'children'};
194             }
195              
196             =head2 Tree::MultiNode::Node::child_keys
197             Tree::MultiNode::Node::child_values
198             Tree::MultiNode::Node::child_kv_pairs
199              
200             These functions return arrays consisting of the appropriate data
201             from the child nodes.
202              
203             my @keys = $node->child_keys();
204             my @vals = $node->child_values();
205             my %kv_pairs = $node->child_kv_pairs();
206              
207             =cut
208              
209             sub child_keys {
210 6     6 1 12 my $self = shift;
211 6         12 my $children = $self->{'children'};
212 6         11 my @keys;
213             my $node;
214              
215 6         14 foreach $node (@$children) {
216 13         22 push @keys, $node->key();
217             }
218              
219 6         26 return @keys;
220             }
221              
222             sub child_values {
223 1     1 1 689 my $self = shift;
224 1         3 my $children = $self->{'children'};
225 1         4 my @values;
226             my $node;
227              
228 1         4 foreach $node (@$children) {
229 3         9 push @values, $node->value();
230             }
231              
232 1         6 return @values;
233             }
234              
235             sub child_kv_pairs {
236 6     6 1 690 my $self = shift;
237 6         12 my $children = $self->{'children'};
238 6         24 my %h;
239             my $node;
240              
241 6         16 foreach $node (@$children) {
242 15         29 $h{ $node->key() } = $node->value();
243             }
244              
245 6         34 return %h;
246             }
247              
248             =head2 Tree::MultiNode::Node::child_key_positions
249              
250             This function returns a hash table that consists of the
251             child keys as the hash keys, and the position in the child
252             array as the value. This allows for a quick and dirty way
253             of looking up the position of a given key in the child list.
254              
255             my %h = $node->child_key_positions();
256              
257             =cut
258              
259             sub child_key_positions {
260 3     3 1 10 my $self = shift;
261 3         6 my $children = $self->{'children'};
262 3         6 my ( %h, $i, $node );
263              
264 3         3 $i = 0;
265 3         6 foreach $node (@$children) {
266 8         16 $h{ $node->key() } = $i++;
267             }
268              
269 3         37 return %h;
270             }
271              
272             =head2 Tree::MultiNode::Node::num_children
273              
274             Returns the number of children for this node.
275              
276             my $count = $node->num_children();
277              
278             =cut
279              
280             sub num_children {
281 36     36 1 59 my $self = shift;
282 36         47 return scalar @{$self->{'children'}};
  36         111  
283             }
284              
285             =head2 Tree::MultiNode::Node::parent
286              
287             Returns a reference to the parent node of the current node.
288              
289             $node_parent = $node3->parent();
290              
291             =cut
292              
293             sub parent {
294 51     51 1 783 my $self = shift;
295 51         162 return $self->{'parent'};
296             }
297              
298             =head2 Tree::MultiNode::Node::dump
299              
300             Used for diagnostics, it prints out the members of the node.
301              
302             $node3->dump();
303              
304             =cut
305              
306             sub dump {
307 2     2 1 42 my $self = shift;
308              
309 17     17   115 no warnings 'uninitialized';
  17         26  
  17         3138  
310 2         6 print "[dump] key: ", $self->{'key'}, "\n";
311 2         5 print "[dump] val: ", $self->{'value'}, "\n";
312 2         4 print "[dump] parent: ", $self->{'parent'}, "\n";
313 2         10 print "[dump] children: ", $self->{'children'}, "\n";
314             }
315              
316             sub _clearrefs {
317 0     0     my $self = shift;
318 0           delete $self->{'parent'};
319 0           my $children = $self->{'children'};
320 0 0         if ( defined $children ) {
321 0           foreach my $child ( @{$children} ) {
  0            
322 0 0         $child->_clearrefs() if defined $child;
323             }
324             }
325 0           delete $self->{'children'};
326             }
327              
328             1;