File Coverage

blib/lib/Class/Accessor/Complex.pm
Criterion Covered Total %
statement 512 570 89.8
branch 136 246 55.2
condition 71 241 29.4
subroutine 97 101 96.0
pod 15 15 100.0
total 831 1173 70.8


line stmt bran cond sub pod time code
1 12     18   344964 use 5.008;
  12         42  
  12         498  
2 12     12   67 use strict;
  12         21  
  12         318  
3 12     12   58 use warnings;
  12         23  
  12         866  
4              
5             package Class::Accessor::Complex;
6             our $VERSION = '1.100880';
7              
8             # ABSTRACT: Arrays, hashes, booleans, integers, sets and more
9 12     12   63 use Carp qw(carp croak cluck);
  12         19  
  12         1325  
10 12     12   10905 use Data::Miscellany 'flatten';
  12         15824  
  12         768  
11 12     12   11622 use List::MoreUtils 'uniq';
  12         19719  
  12         1101  
12 12     12   87 use parent qw(Class::Accessor Class::Accessor::Installer);
  12         22  
  12         109  
13              
14             sub mk_new {
15 14     14 1 244 my ($self, @args) = @_;
16 14   33     117 my $class = ref $self || $self;
17 14 50       76 @args = ('new') unless @args;
18 14         38 for my $name (@args) {
19             $self->install_accessor(
20             name => $name,
21             code => sub {
22 36 50 33 36   3012 local $DB::sub = local *__ANON__ = "${class}::${name}"
        36      
23             if defined &DB::DB && !$Devel::DProf::VERSION;
24              
25             # don't use $class, as that's already defined above
26 36         71 my $this_class = shift;
27 36 50       139 my $self = ref($this_class) ? $this_class : bless {},
28             $this_class;
29 0         0 my %args =
30             (scalar(@_ == 1) && ref($_[0]) eq 'HASH')
31 36 50 33     187 ? %{ $_[0] }
32             : @_;
33 36         146 $self->$_($args{$_}) for keys %args;
34 36 50       333 $self->init(%args) if $self->can('init');
35 36         178 $self;
36             },
37 14         266 );
38 14         673 $self->document_accessor(
39             name => $name,
40             purpose => <<'EODOC',
41             Creates and returns a new object. The constructor will accept as arguments a
42             list of pairs, from component name to initial value. For each pair, the named
43             component is initialized by calling the method of the same name with the given
44             value. If called with a single hash reference, it is dereferenced and its
45             key/value pairs are set as described before.
46             EODOC
47             examples => [
48             "my \$obj = $class->$name;",
49             "my \$obj = $class->$name(\%args);",
50             ],
51             );
52             }
53 14         8674 $self; # for chaining
54             }
55              
56             sub mk_singleton {
57 1     1 1 20 my ($self, @args) = @_;
58 1   33     9 my $class = ref $self || $self;
59 1 50       6 @args = ('new') unless @args;
60 1         2 my $singleton;
61 1         2 for my $name (@args) {
62             $self->install_accessor(
63             name => $name,
64             code => sub {
65 3 50 33 3   16 local $DB::sub = local *__ANON__ = "${class}::${name}"
66             if defined &DB::DB && !$Devel::DProf::VERSION;
67 3 100       12 return $singleton if defined $singleton;
68              
69             # don't use $class, as that's already defined above
70 1         3 my $this_class = shift;
71 1 50       7 $singleton =
72             ref($this_class)
73             ? $this_class
74             : bless {}, $this_class;
75 0         0 my %args =
76             (scalar(@_ == 1) && ref($_[0]) eq 'HASH')
77 1 50 33     9 ? %{ $_[0] }
78             : @_;
79 1         8 $singleton->$_($args{$_}) for keys %args;
80 1 50       12 $singleton->init(%args) if $singleton->can('init');
81 1         5 $singleton;
82             },
83 1         20 );
84 1         51 $self->document_accessor(
85             name => $name,
86             purpose => <<'EODOC',
87             Creates and returns a new object. The object will be a singleton, so repeated
88             calls to the constructor will always return the same object. The constructor
89             will accept as arguments a list of pairs, from component name to initial
90             value. For each pair, the named component is initialized by calling the
91             method of the same name with the given value. If called with a single hash
92             reference, it is dereferenced and its key/value pairs are set as described
93             before.
94             EODOC
95             examples => [
96             "my \$obj = $class->$name;",
97             "my \$obj = $class->$name(\%args);",
98             ],
99             );
100             }
101 1         590 $self; # for chaining
102             }
103              
104             sub mk_scalar_accessors {
105 3     3 1 10 my ($self, @fields) = @_;
106 3   33     23 my $class = ref $self || $self;
107 3         8 for my $field (@fields) {
108             $self->install_accessor(
109             name => $field,
110             code => sub {
111 14 50 33 14   53 local $DB::sub = local *__ANON__ = "${class}::${field}"
112             if defined &DB::DB && !$Devel::DProf::VERSION;
113 14 100       69 return $_[0]->{$field} if @_ == 1;
114 5         42 $_[0]->{$field} = $_[1];
115             },
116 4         468 );
117 4         156 $self->document_accessor(
118             name => $field,
119             purpose => <<'EODOC',
120             A basic getter/setter method. If called without an argument, it returns the
121             value. If called with a single argument, it sets the value.
122             EODOC
123             examples =>
124             [ "my \$value = \$obj->$field;", "\$obj->$field(\$value);", ],
125             );
126 4         1791 my @clear_methods = uniq "clear_${field}", "${field}_clear";
127 4         14 for my $name (@clear_methods) {
128             $self->install_accessor(
129             name => $name,
130             code => sub {
131 0 0 0 7   0 local $DB::sub = local *__ANON__ = "${class}::${name}"
132             if defined &DB::DB && !$Devel::DProf::VERSION;
133 0         0 $_[0]->{$field} = undef;
134             },
135 8         155 );
136             }
137             $self->document_accessor(
138 4         105 name => \@clear_methods,
139             purpose => 'Clears the value.',
140             examples => ["\$obj->$clear_methods[0];"],
141             belongs_to => $field,
142             );
143             }
144 3         1229 $self; # for chaining
145             }
146              
147             sub mk_class_scalar_accessors {
148 1     1 1 4 my ($self, @fields) = @_;
149 1   33     10 my $class = ref $self || $self;
150 1         2 for my $field (@fields) {
151 1         2 my $scalar;
152             $self->install_accessor(
153             name => $field,
154             code => sub {
155 5 50 33 5   21 local $DB::sub = local *__ANON__ = "${class}::${field}"
156             if defined &DB::DB && !$Devel::DProf::VERSION;
157 5 100       24 return $scalar if @_ == 1;
158 1         2 $scalar = $_[1];
159             },
160 1         9 );
161 1         34 $self->document_accessor(
162             name => $field,
163             purpose => <<'EODOC',
164             A basic getter/setter method. This is a class variable, so it is shared
165             between all instances of this class. Changing it in one object will change it
166             for all other objects as well. If called without an argument, it returns the
167             value. If called with a single argument, it sets the value.
168             EODOC
169             examples =>
170             [ "my \$value = \$obj->$field;", "\$obj->$field(\$value);", ],
171             );
172 1         474 my @clear_methods = uniq "clear_${field}", "${field}_clear";
173 1         4 for my $name (@clear_methods) {
174             $self->install_accessor(
175             name => $name,
176             code => sub {
177 1 50 33 1   6 local $DB::sub = local *__ANON__ = "${class}::${name}"
178             if defined &DB::DB && !$Devel::DProf::VERSION;
179 1         2 $scalar = undef;
180             },
181 2         36 );
182             }
183             $self->document_accessor(
184 1         27 name => \@clear_methods,
185             purpose => <<'EODOC',
186             Clears the value. Since this is a class variable, the value will be undefined
187             for all instances of this class.
188             EODOC
189             example => "\$obj->$clear_methods[0];",
190             belongs_to => $field,
191             );
192             }
193 1         425 $self; # for chaining
194             }
195              
196             sub mk_concat_accessors {
197 1     2 1 5 my ($self, @args) = @_;
198 1   33     11 my $class = ref $self || $self;
199 1         2 for my $arg (@args) {
200              
201             # defaults
202 2         487 my $field = $arg;
203 2         4 my $join = '';
204 2 100       6 if (ref $arg eq 'ARRAY') {
205 1         4 ($field, $join) = @$arg;
206             }
207             $self->install_accessor(
208             name => $field,
209             code => sub {
210 11 50 33 12   45 local $DB::sub = local *__ANON__ = "${class}::${field}"
211             if defined &DB::DB && !$Devel::DProf::VERSION;
212 11         17 my ($self, $text) = @_;
213 11 100       24 if (defined $text) {
214 4 100       46 if (defined $self->{$field}) {
215 2         9 $self->{$field} = $self->{$field} . $join . $text;
216             } else {
217 2         6 $self->{$field} = $text;
218             }
219             }
220 11         53 return $self->{$field};
221             },
222 2         17 );
223 2         67 $self->document_accessor(
224             name => $field,
225              
226             # FIXME use the current value of $join in the docs
227             purpose => <<'EODOC',
228             A getter/setter method. If called without an argument, it returns the
229             value. If called with a single argument, it appends to the current value.
230             EODOC
231             examples =>
232             [ "my \$value = \$obj->$field;", "\$obj->$field(\$value);", ],
233             );
234 2         1016 my @clear_methods = uniq "clear_${field}", "${field}_clear";
235 2         7 for my $name (@clear_methods) {
236             $self->install_accessor(
237             name => $name,
238             code => sub {
239 2 50 33 2   11 local $DB::sub = local *__ANON__ = "${class}::${name}"
240             if defined &DB::DB && !$Devel::DProf::VERSION;
241 2         7 $_[0]->{$field} = undef;
242             },
243 4         79 );
244             }
245             $self->document_accessor(
246 2         56 name => \@clear_methods,
247             purpose => <<'EODOC',
248             Clears the value.
249             EODOC
250             example => "\$obj->$clear_methods[0];",
251             belongs_to => $field,
252             );
253             }
254 1         521 $self; # for chaining
255             }
256              
257             sub mk_array_accessors {
258 1     3 1 4 my ($self, @fields) = @_;
259 1   33     8 my $class = ref $self || $self;
260 1         2 for my $field (@fields) {
261             $self->install_accessor(
262             name => $field,
263             code => sub {
264 6 50 33 8   1430 local $DB::sub = local *__ANON__ = "${class}::${field}"
265             if defined &DB::DB && !$Devel::DProf::VERSION;
266 6         13 my ($self, @list) = @_;
267 6 100       16 defined $self->{$field} or $self->{$field} = [];
268 1 50       3 @{ $self->{$field} } =
  4         9  
269 6 100       14 map { ref $_ eq 'ARRAY' ? @$_ : ($_) } @list
270             if @list;
271 6 100       13 wantarray ? @{ $self->{$field} } : $self->{$field};
  5         30  
272             },
273 1         9 );
274 1         33 $self->document_accessor(
275             name => $field,
276             purpose => <<'EODOC',
277             Get or set the array values. If called without arguments, it returns the
278             array in list context, or a reference to the array in scalar context. If
279             called with arguments, it expands array references found therein and sets the
280             values.
281             EODOC
282             examples => [
283             "my \@values = \$obj->$field;",
284             "my \$array_ref = \$obj->$field;",
285             "\$obj->$field(\@values);",
286             "\$obj->$field(\$array_ref);",
287             ],
288             );
289 1         419 my @push_methods = uniq "push_${field}", "${field}_push";
290 1         4 for my $name (@push_methods) {
291             $self->install_accessor(
292             name => $name,
293             code => sub {
294 1 50 33 3   647 local $DB::sub = local *__ANON__ = "${class}::${name}"
295             if defined &DB::DB && !$Devel::DProf::VERSION;
296 1         2 my $self = shift;
297 1         2 push @{ $self->{$field} } => @_;
  1         4  
298             },
299 2         36 );
300             }
301             $self->document_accessor(
302 1         26 name => \@push_methods,
303             belongs_to => $field,
304             purpose => 'Pushes elements onto the end of the array.',
305             examples => ["\$obj->$push_methods[0](\@values);"],
306             );
307 1         340 my @pop_methods = uniq "pop_${field}", "${field}_pop";
308 1         4 for my $name (@pop_methods) {
309             $self->install_accessor(
310             name => $name,
311             code => sub {
312 1 50 33 4   9 local $DB::sub = local *__ANON__ = "${class}::${name}"
313             if defined &DB::DB && !$Devel::DProf::VERSION;
314 1         2 pop @{ $_[0]->{$field} };
  1         3  
315             },
316 2         29 );
317             }
318             $self->document_accessor(
319 1         25 name => \@pop_methods,
320             purpose => <<'EODOC',
321             Pops the last element off the array, returning it.
322             EODOC
323             examples => ["my \$value = \$obj->$pop_methods[0];"],
324             belongs_to => $field,
325             );
326 1         367 my @unshift_methods = uniq "unshift_${field}", "${field}_unshift";
327 1         3 for my $name (@unshift_methods) {
328             $self->install_accessor(
329             name => $name,
330             code => sub {
331 0 0 0 2   0 local $DB::sub = local *__ANON__ = "${class}::${name}"
332             if defined &DB::DB && !$Devel::DProf::VERSION;
333 0         0 my $self = shift;
334 0         0 unshift @{ $self->{$field} } => @_;
  0         0  
335             },
336 2         33 );
337             }
338             $self->document_accessor(
339 1         24 name => \@unshift_methods,
340             purpose => <<'EODOC',
341             Unshifts elements onto the beginning of the array.
342             EODOC
343             examples => ["\$obj->$unshift_methods[0](\@values);"],
344             belongs_to => $field,
345             );
346 1         379 my @shift_methods = uniq "shift_${field}", "${field}_shift";
347 1         3 for my $name (@shift_methods) {
348             $self->install_accessor(
349             name => $name,
350             code => sub {
351 1 50 33 2   6 local $DB::sub = local *__ANON__ = "${class}::${name}"
352             if defined &DB::DB && !$Devel::DProf::VERSION;
353 1         1 shift @{ $_[0]->{$field} };
  1         4  
354             },
355 2         31 );
356             }
357             $self->document_accessor(
358 1         25 name => \@shift_methods,
359             purpose => <<'EODOC',
360             Shifts the first element off the array, returning it.
361             EODOC
362             examples => ["my \$value = \$obj->$shift_methods[0];"],
363             belongs_to => $field,
364             );
365 1         409 my @clear_methods = uniq "clear_${field}", "${field}_clear";
366 1         3 for my $name (@clear_methods) {
367             $self->install_accessor(
368             name => $name,
369             code => sub {
370 0 0 0 1   0 local $DB::sub = local *__ANON__ = "${class}::${name}"
371             if defined &DB::DB && !$Devel::DProf::VERSION;
372 0         0 $_[0]->{$field} = [];
373             },
374 2         37 );
375             }
376             $self->document_accessor(
377 1         29 name => \@clear_methods,
378             purpose => <<'EODOC',
379             Deletes all elements from the array.
380             EODOC
381             examples => ["\$obj->$clear_methods[0];"],
382             belongs_to => $field,
383             );
384 1         428 my @count_methods = uniq "count_${field}", "${field}_count";
385 1         3 for my $name (@count_methods) {
386             $self->install_accessor(
387             name => $name,
388             code => sub {
389 6 50 33 7   22 local $DB::sub = local *__ANON__ = "${class}::${name}"
390             if defined &DB::DB && !$Devel::DProf::VERSION;
391 6 100       29 exists $_[0]->{$field} ? scalar @{ $_[0]->{$field} } : 0;
  5         20  
392             },
393 2         31 );
394             }
395             $self->document_accessor(
396 1         41 name => \@count_methods,
397             purpose => <<'EODOC',
398             Returns the number of elements in the array.
399             EODOC
400             examples => ["my \$count = \$obj->$count_methods[0];"],
401             belongs_to => $field,
402             );
403 1         402 my @splice_methods = uniq "splice_${field}", "${field}_splice";
404 1         5 for my $name (@splice_methods) {
405             $self->install_accessor(
406             name => $name,
407             code => sub {
408 1 50 33 7   7 local $DB::sub = local *__ANON__ = "${class}::${name}"
409             if defined &DB::DB && !$Devel::DProf::VERSION;
410 1         3 my ($self, $offset, $len, @list) = @_;
411 1         4 splice(@{ $self->{$field} }, $offset, $len, @list);
  1         8  
412             },
413 2         35 );
414             }
415             $self->document_accessor(
416 1         26 name => \@splice_methods,
417             purpose => <<'EODOC',
418             Takes three arguments: An offset, a length and a list.
419              
420             Removes the elements designated by the offset and the length from the array,
421             and replaces them with the elements of the list, if any. In list context,
422             returns the elements removed from the array. In scalar context, returns the
423             last element removed, or C if no elements are removed. The array grows
424             or shrinks as necessary. If the offset is negative then it starts that far
425             from the end of the array. If the length is omitted, removes everything from
426             the offset onward. If the length is negative, removes the elements from the
427             offset onward except for -length elements at the end of the array. If both the
428             offset and the length are omitted, removes everything. If the offset is past
429             the end of the array, it issues a warning, and splices at the end of the
430             array.
431             EODOC
432             examples => [
433             "\$obj->$splice_methods[0](2, 1, \$x, \$y);",
434             "\$obj->$splice_methods[0](-1);",
435             "\$obj->$splice_methods[0](0, -1);",
436             ],
437             belongs_to => $field,
438             );
439 1         365 my @index_methods = uniq "index_${field}", "${field}_index";
440 1         3 for my $name (@index_methods) {
441             $self->install_accessor(
442             name => $name,
443             code => sub {
444 3 50 33 10   366 local $DB::sub = local *__ANON__ = "${class}::${name}"
445             if defined &DB::DB && !$Devel::DProf::VERSION;
446 3         192 my ($self, @indices) = @_;
447 3         6 my @result = map { $self->{$field}[$_] } @indices;
  5         15  
448 3 100       197 return $result[0] if @indices == 1;
449 1 50       9 wantarray ? @result : \@result;
450             },
451 2         32 );
452             }
453             $self->document_accessor(
454 1         26 name => \@index_methods,
455             purpose => <<'EODOC',
456             Takes a list of indices and returns the elements indicated by those indices.
457             If only one index is given, the corresponding array element is returned. If
458             several indices are given, the result is returned as an array in list context
459             or as an array reference in scalar context.
460             EODOC
461             examples => [
462             "my \$element = \$obj->$index_methods[0](3);",
463             "my \@elements = \$obj->$index_methods[0](\@indices);",
464             "my \$array_ref = \$obj->$index_methods[0](\@indices);",
465             ],
466             belongs_to => $field,
467             );
468 1         832 my @set_methods = uniq "set_${field}", "${field}_set";
469 1         4 for my $name (@set_methods) {
470             $self->install_accessor(
471             name => $name,
472             code => sub {
473 0 0 0 4   0 local $DB::sub = local *__ANON__ = "${class}::${$name}"
  0         0  
474             if defined &DB::DB && !$Devel::DProf::VERSION;
475 0         0 my $self = shift;
476 0         0 my @args = @_;
477 0 0       0 croak
478             "${class}::${field}_set expects an even number of fields\n"
479             if @args % 2;
480 0         0 while (my ($index, $value) = splice @args, 0, 2) {
481 0         0 $self->{$field}->[$index] = $value;
482             }
483 0         0 return @_ / 2;
484             },
485 2         45 );
486             }
487             $self->document_accessor(
488 1         29 name => \@set_methods,
489             purpose => <<'EODOC',
490             Takes a list of index/value pairs and for each pair it sets the array element
491             at the indicated index to the indicated value. Returns the number of elements
492             that have been set.
493             EODOC
494             examples => ["\$obj->$set_methods[0](1 => \$x, 5 => \$y);"],
495             belongs_to => $field,
496             );
497             }
498 1         477 $self; # for chaining
499             }
500              
501             sub mk_class_array_accessors {
502 1     4 1 5 my ($self, @fields) = @_;
503 1   33     12 my $class = ref $self || $self;
504 1         3 for my $field (@fields) {
505 1         3 my @array;
506             $self->install_accessor(
507             name => $field,
508             code => sub {
509 16 50 33 16   2437 local $DB::sub = local *__ANON__ = "${class}::${field}"
510             if defined &DB::DB && !$Devel::DProf::VERSION;
511 16         26 my ($self, @list) = @_;
512 16 50       30 @array = map { ref $_ eq 'ARRAY' ? @$_ : ($_) } @list
  4 100       11  
513             if @list;
514 16 100       92 wantarray ? @array : \@array;
515             },
516 1         13 );
517 1         51 $self->document_accessor(
518             name => $field,
519             purpose => <<'EODOC',
520             Get or set the array values. If called without an arguments, it returns the
521             array in list context, or a reference to the array in scalar context. If
522             called with arguments, it expands array references found therein and sets the
523             values.
524              
525             This is a class variable, so it is shared between all instances of this class.
526             Changing it in one object will change it for all other objects as well.
527             EODOC
528             examples => [
529             "my \@values = \$obj->$field;",
530             "my \$array_ref = \$obj->$field;",
531             "\$obj->$field(\@values);",
532             "\$obj->$field(\$array_ref);",
533             ],
534             );
535 1         462 my @push_methods = uniq "push_${field}", "${field}_push";
536 1         4 for my $name (@push_methods) {
537             $self->install_accessor(
538             name => $name,
539             code => sub {
540 1 50 33 1   5 local $DB::sub = local *__ANON__ = "${class}::${name}"
541             if defined &DB::DB && !$Devel::DProf::VERSION;
542 1         2 my $self = shift;
543 1         3 push @array => @_;
544             },
545 2         38 );
546             }
547             $self->document_accessor(
548 1         28 name => \@push_methods,
549             purpose => <<'EODOC',
550             Pushes elements onto the end of the array. Since this is a class variable, the
551             value will be changed for all instances of this class.
552             EODOC
553             examples => ["\$obj->$push_methods[0](\@values);"],
554             belongs_to => $field,
555             );
556 1         429 my @pop_methods = uniq "pop_${field}", "${field}_pop";
557 1         4 for my $name (@pop_methods) {
558             $self->install_accessor(
559             name => $name,
560             code => sub {
561 1 50 33 2   7 local $DB::sub = local *__ANON__ = "${class}::${name}"
562             if defined &DB::DB && !$Devel::DProf::VERSION;
563 1         4 pop @array;
564             },
565 2         37 );
566             }
567             $self->document_accessor(
568 1         28 name => \@pop_methods,
569             purpose => <<'EODOC',
570             Pops the last element off the array, returning it. Since this is a class
571             variable, the value will be changed for all instances of this class.
572             EODOC
573             examples => ["my \$value = \$obj->$pop_methods[0];"],
574             belongs_to => $field,
575             );
576 1         443 my @field_methods = uniq "unshift_${field}", "${field}_unshift";
577 1         5 for my $name (@field_methods) {
578             $self->install_accessor(
579             name => $name,
580             code => sub {
581 0 0 0 2   0 local $DB::sub = local *__ANON__ = "${class}::${name}"
582             if defined &DB::DB && !$Devel::DProf::VERSION;
583 0         0 my $self = shift;
584 0         0 unshift @array => @_;
585             },
586 2         38 );
587             }
588             $self->document_accessor(
589 1         32 name => \@field_methods,
590             purpose => <<'EODOC',
591             Unshifts elements onto the beginning of the array. Since this is a class
592             variable, the value will be changed for all instances of this class.
593             EODOC
594             examples => ["\$obj->$field_methods[0](\@values);"],
595             belongs_to => $field,
596             );
597 1         448 my @shift_methods = uniq "shift_${field}", "${field}_shift";
598 1         4 for my $name (@shift_methods) {
599             $self->install_accessor(
600             name => $name,
601             code => sub {
602 1 50 33 2   6 local $DB::sub = local *__ANON__ = "${class}::${name}"
603             if defined &DB::DB && !$Devel::DProf::VERSION;
604 1         2 shift @array;
605             },
606 2         38 );
607             }
608             $self->document_accessor(
609 1         30 name => \@shift_methods,
610             purpose => <<'EODOC',
611             Shifts the first element off the array, returning it. Since this is a class
612             variable, the value will be changed for all instances of this class.
613             EODOC
614             examples => ["my \$value = \$obj->$shift_methods[0];"],
615             belongs_to => $field,
616             );
617 1         530 my @clear_methods = uniq "clear_${field}", "${field}_clear";
618 1         4 for my $name (@clear_methods) {
619             $self->install_accessor(
620             name => $name,
621             code => sub {
622 0 0 0 1   0 local $DB::sub = local *__ANON__ = "${class}::${name}"
623             if defined &DB::DB && !$Devel::DProf::VERSION;
624 0         0 @array = ();
625             },
626 2         39 );
627             }
628             $self->document_accessor(
629 1         29 name => \@clear_methods,
630             purpose => <<'EODOC',
631             Deletes all elements from the array. Since this is a class variable, the value
632             will be changed for all instances of this class.
633             EODOC
634             examples => ["\$obj->$clear_methods[0];"],
635             belongs_to => $field,
636             );
637 1         478 my @count_methods = uniq "count_${field}", "${field}_count";
638 1         3 for my $name (@count_methods) {
639             $self->install_accessor(
640             name => $name,
641             code => sub {
642 6 50 33 7   22 local $DB::sub = local *__ANON__ = "${class}::${name}"
643             if defined &DB::DB && !$Devel::DProf::VERSION;
644 6         28 scalar @array;
645             },
646 2         51 );
647             }
648             $self->document_accessor(
649 1         26 name => \@count_methods,
650             purpose => <<'EODOC',
651             Returns the number of elements in the array. Since this is a class variable,
652             the value will be changed for all instances of this class.
653             EODOC
654             examples => ["my \$count = \$obj->$count_methods[0];"],
655             belongs_to => $field,
656             );
657 1         414 my @splice_methods = uniq "splice_${field}", "${field}_splice";
658 1         4 for my $name (@splice_methods) {
659             $self->install_accessor(
660             name => $name,
661             code => sub {
662 1 50 33 7   29 local $DB::sub = local *__ANON__ = "${class}::${name}"
663             if defined &DB::DB && !$Devel::DProf::VERSION;
664 1         3 my ($self, $offset, $len, @list) = @_;
665 1         7 splice(@array, $offset, $len, @list);
666             },
667 2         40 );
668             }
669             $self->document_accessor(
670 1         33 name => \@splice_methods,
671             purpose => <<'EODOC',
672             Takes three arguments: An offset, a length and a list.
673              
674             Removes the elements designated by the offset and the length from the array,
675             and replaces them with the elements of the list, if any. In list context,
676             returns the elements removed from the array. In scalar context, returns the
677             last element removed, or C if no elements are removed. The array grows
678             or shrinks as necessary. If the offset is negative then it starts that far
679             from the end of the array. If the length is omitted, removes everything from
680             the offset onward. If the length is negative, removes the elements from the
681             offset onward except for -length elements at the end of the array. If both the
682             offset and the length are omitted, removes everything. If the offset is past
683             the end of the array, it issues a warning, and splices at the end of the
684             array.
685              
686             Since this is a class variable, the value will be changed for all instances of
687             this class.
688             EODOC
689             examples => [
690             "\$obj->$splice_methods[0](2, 1, \$x, \$y);",
691             "\$obj->$splice_methods[0](-1);",
692             "\$obj->$splice_methods[0](0, -1);",
693             ],
694             belongs_to => $field,
695             );
696 1         476 my @index_methods = uniq "index_${field}", "${field}_index";
697 1         3 for my $name (@index_methods) {
698             $self->install_accessor(
699             name => $name,
700             code => sub {
701 3 50 33 10   19 local $DB::sub = local *__ANON__ = "${class}::${name}"
702             if defined &DB::DB && !$Devel::DProf::VERSION;
703 3         8 my ($self, @indices) = @_;
704 3         7 my @result = map { $array[$_] } @indices;
  5         15  
705 3 100       20 return $result[0] if @indices == 1;
706 1 50       10 wantarray ? @result : \@result;
707             },
708 2         33 );
709             }
710             $self->document_accessor(
711 1         26 name => \@index_methods,
712             purpose => <<'EODOC',
713             Takes a list of indices and returns the elements indicated by those indices.
714             If only one index is given, the corresponding array element is returned. If
715             several indices are given, the result is returned as an array in list context
716             or as an array reference in scalar context.
717              
718             Since this is a class variable, the value will be changed for all instances of
719             this class.
720             EODOC
721             examples => [
722             "my \$element = \$obj->$index_methods[0](3);",
723             "my \@elements = \$obj->$index_methods[0](\@indices);",
724             "my \$array_ref = \$obj->$index_methods[0](\@indices);",
725             ],
726             belongs_to => $field,
727             );
728 1         359 my @set_methods = uniq "set_${field}", "${field}_set";
729 1         3 for my $name (@set_methods) {
730             $self->install_accessor(
731             name => $name,
732             code => sub {
733 0 0 0 4   0 local $DB::sub = local *__ANON__ = "${class}::${name}"
734             if defined &DB::DB && !$Devel::DProf::VERSION;
735 0         0 my $self = shift;
736 0         0 my @args = @_;
737 0 0       0 croak
738             "${class}::${field}_set expects an even number of fields\n"
739             if @args % 2;
740 0         0 while (my ($index, $value) = splice @args, 0, 2) {
741 0         0 $array[$index] = $value;
742             }
743 0         0 return @_ / 2;
744             },
745 2         31 );
746             }
747             $self->document_accessor(
748 1         23 name => \@set_methods,
749             purpose => <<'EODOC',
750             Takes a list of index/value pairs and for each pair it sets the array element
751             at the indicated index to the indicated value. Returns the number of elements
752             that have been set. Since this is a class variable, the value will be changed
753             for all instances of this class.
754             EODOC
755             examples => ["\$obj->$set_methods[0](1 => \$x, 5 => \$y);"],
756             belongs_to => $field,
757             );
758             }
759 1         346 $self; # for chaining
760             }
761              
762             sub mk_hash_accessors {
763 1     4 1 5 my ($self, @fields) = @_;
764 1   33     11 my $class = ref $self || $self;
765 1         3 for my $field (@fields) {
766             $self->install_accessor(
767             name => $field,
768             code => sub {
769 9 50 33 9   806 local $DB::sub = local *__ANON__ = "${class}::${field}"
770             if defined &DB::DB && !$Devel::DProf::VERSION;
771 9         23 my ($self, @list) = @_;
772 9 50       27 defined $self->{$field} or $self->{$field} = {};
773 9 100       25 if (scalar @list == 1) {
774 3         8 my ($key) = @list;
775 3 100       10 if (my $type = ref $key) {
776 2 100       10 if ($type eq 'ARRAY') {
    50          
777 1         2 return @{ $self->{$field} }{@$key};
  1         26  
778             } elsif ($type eq 'HASH') {
779 1         8 while (my ($subkey, $value) = each %$key) {
780 2         10 $self->{$field}{$subkey} = $value;
781             }
782             return wantarray
783 1 50       6 ? %{ $self->{$field} }
  0         0  
784             : $self->{$field};
785             } else {
786 0         0 cluck
787             "Unrecognized ref type for hash method: $type.";
788             }
789             } else {
790 1         7 return $self->{$field}{$key};
791             }
792             } else {
793 6         7 while (1) {
794 10         17 my $key = shift @list;
795 10 100       25 defined $key or last;
796 4         8 my $value = shift @list;
797 4 50       8 defined $value or carp "No value for key $key.";
798 4         22 $self->{$field}{$key} = $value;
799             }
800 6 100       19 return wantarray ? %{ $self->{$field} } : $self->{$field};
  4         38  
801             }
802             },
803 1         13 );
804 1         43 $self->document_accessor(
805             name => $field,
806             purpose => <<'EODOC',
807             Get or set the hash values. If called without arguments, it returns the hash
808             in list context, or a reference to the hash in scalar context. If called
809             with a list of key/value pairs, it sets each key to its corresponding value,
810             then returns the hash as described before.
811              
812             If called with exactly one key, it returns the corresponding value.
813              
814             If called with exactly one array reference, it returns an array whose elements
815             are the values corresponding to the keys in the argument array, in the same
816             order. The resulting list is returned as an array in list context, or a
817             reference to the array in scalar context.
818              
819             If called with exactly one hash reference, it updates the hash with the given
820             key/value pairs, then returns the hash in list context, or a reference to the
821             hash in scalar context.
822             EODOC
823             examples => [
824             "my \%hash = \$obj->$field;",
825             "my \$hash_ref = \$obj->$field;",
826             "my \$value = \$obj->$field(\$key);",
827             "my \@values = \$obj->$field([ qw(foo bar) ]);",
828             "\$obj->$field(\%other_hash);",
829             "\$obj->$field(foo => 23, bar => 42);",
830             ],
831             );
832 1         569 my @clear_methods = uniq "clear_${field}", "${field}_clear";
833 1         4 for my $name (@clear_methods) {
834             $self->install_accessor(
835             name => $name,
836             code => sub {
837 1 50 33 1   8 local $DB::sub = local *__ANON__ = "${class}::${name}"
838             if defined &DB::DB && !$Devel::DProf::VERSION;
839 1         2 my $self = shift;
840 1         4 $self->{$field} = {};
841             },
842 2         40 );
843             }
844             $self->document_accessor(
845 1         30 name => \@clear_methods,
846             purpose => <<'EODOC',
847             Deletes all keys and values from the hash.
848             EODOC
849             examples => ["\$obj->$clear_methods[0];"],
850             belongs_to => $field,
851             );
852 1         582 my @keys_methods = uniq "keys_${field}", "${field}_keys";
853 1         4 for my $name (@keys_methods) {
854             $self->install_accessor(
855             name => $name,
856             code => sub {
857 3 50 33 4   17 local $DB::sub = local *__ANON__ = "${class}::${name}"
858             if defined &DB::DB && !$Devel::DProf::VERSION;
859 3         4 keys %{ $_[0]->{$field} };
  3         35  
860             },
861 2         38 );
862             }
863             $self->document_accessor(
864 1         33 name => \@keys_methods,
865             purpose => <<'EODOC',
866             Returns a list of all hash keys in no particular order.
867             EODOC
868             examples => ["my \@keys = \$obj->$keys_methods[0];"],
869             belongs_to => $field,
870             );
871 1         549 my @count_methods = uniq "count_${field}", "${field}_count";
872 1         5 for my $name (@count_methods) {
873             $self->install_accessor(
874             name => $name,
875             code => sub {
876 3 50 33 7   15 local $DB::sub = local *__ANON__ = "${class}::${name}"
877             if defined &DB::DB && !$Devel::DProf::VERSION;
878 3         4 scalar keys %{ $_[0]->{$field} };
  3         23  
879             },
880 2         41 );
881             }
882             $self->document_accessor(
883 1         32 name => \@count_methods,
884             purpose => <<'EODOC',
885             Returns the number of keys in the hash.
886             EODOC
887             examples => ["my \$count = \$obj->$count_methods[0];"],
888             belongs_to => $field,
889             );
890 1         457 my @values_methods = uniq "values_${field}", "${field}_values";
891 1         5 for my $name (@values_methods) {
892             $self->install_accessor(
893             name => $name,
894             code => sub {
895 1 50 33 7   6 local $DB::sub = local *__ANON__ = "${class}::${name}"
896             if defined &DB::DB && !$Devel::DProf::VERSION;
897 1         2 values %{ $_[0]->{$field} };
  1         8  
898             },
899 2         37 );
900             }
901             $self->document_accessor(
902 1         32 name => \@values_methods,
903             purpose => <<'EODOC',
904             Returns a list of all hash values in no particular order.
905             EODOC
906             examples => ["my \@values = \$obj->$values_methods[0];"],
907             belongs_to => $field,
908             );
909 1         442 my @exists_methods = uniq "exists_${field}", "${field}_exists";
910 1         4 for my $name (@exists_methods) {
911             $self->install_accessor(
912             name => $name,
913             code => sub {
914 3 50 33 7   988 local $DB::sub = local *__ANON__ = "${class}::${name}"
915             if defined &DB::DB && !$Devel::DProf::VERSION;
916 3         5 my ($self, $key) = @_;
917 3 50       31 exists $self->{$field} && exists $self->{$field}{$key};
918             },
919 2         40 );
920             }
921             $self->document_accessor(
922 1         30 name => \@exists_methods,
923             purpose => <<'EODOC',
924             Takes a key and returns a true value if the key exists in the hash, and a
925             false value otherwise.
926             EODOC
927             examples => ["if (\$obj->$exists_methods[0](\$key)) { ... }"],
928             belongs_to => $field,
929             );
930 1         474 my @delete_methods = uniq "delete_${field}", "${field}_delete";
931 1         3 for my $name (@delete_methods) {
932             $self->install_accessor(
933             name => $name,
934             code => sub {
935 1 50 33 5   6 local $DB::sub = local *__ANON__ = "${class}::${name}"
936             if defined &DB::DB && !$Devel::DProf::VERSION;
937 1         4 my ($self, @keys) = @_;
938 1         11 delete @{ $self->{$field} }{@keys};
  1         5  
939             },
940 2         39 );
941             }
942             $self->document_accessor(
943 1         56 name => \@delete_methods,
944             purpose =>
945             'Takes a list of keys and deletes those keys from the hash.',
946             examples => ["\$obj->$delete_methods[0](\@keys);"],
947             belongs_to => $field,
948             );
949             }
950 1         433 $self; # for chaining
951             }
952              
953             sub mk_class_hash_accessors {
954 1     5 1 6 my ($self, @fields) = @_;
955 1   33     11 my $class = ref $self || $self;
956 1         5 for my $field (@fields) {
957 1         2 my %hash;
958             $self->install_accessor(
959             name => $field,
960             code => sub {
961 10 50 33 11   38 local $DB::sub = local *__ANON__ = "${class}::${field}"
        68      
962             if defined &DB::DB && !$Devel::DProf::VERSION;
963 10         23 my ($self, @list) = @_;
964 10 100       23 if (scalar @list == 1) {
965 3         5 my ($key) = @list;
966 3 100       14 return $hash{$key} unless ref $key;
967 2 100       12 return @hash{@$key} if ref $key eq 'ARRAY';
968 1 50       4 if (ref($key) eq 'HASH') {
969 1         8 %hash = (%hash, %$key);
970 1 50       7 return wantarray ? %hash : \%hash;
971             }
972              
973             # not a scalar, array or hash...
974 0         0 cluck sprintf
975             'Not a recognized ref type for static hash [%s]',
976             ref($key);
977             } else {
978 7         8 while (1) {
979 11         16 my $key = shift @list;
980 11 100       28 defined $key or last;
981 4         5 my $value = shift @list;
982 4 50       9 defined $value or carp "No value for key $key.";
983 4         11 $hash{$key} = $value;
984             }
985 7 100       68 return wantarray ? %hash : \%hash;
986             }
987             },
988 1         11 );
989 1         45 $self->document_accessor(
990             name => $field,
991             purpose => <<'EODOC',
992             Get or set the hash values. If called without arguments, it returns the hash
993             in list context, or a reference to the hash in scalar context. If called
994             with a list of key/value pairs, it sets each key to its corresponding value,
995             then returns the hash as described before.
996              
997             If called with exactly one key, it returns the corresponding value.
998              
999             If called with exactly one array reference, it returns an array whose elements
1000             are the values corresponding to the keys in the argument array, in the same
1001             order. The resulting list is returned as an array in list context, or a
1002             reference to the array in scalar context.
1003              
1004             If called with exactly one hash reference, it updates the hash with the given
1005             key/value pairs, then returns the hash in list context, or a reference to the
1006             hash in scalar context.
1007              
1008             This is a class variable, so it is shared between all instances of this class.
1009             Changing it in one object will change it for all other objects as well.
1010             EODOC
1011             examples => [
1012             "my \%hash = \$obj->$field;",
1013             "my \$hash_ref = \$obj->$field;",
1014             "my \$value = \$obj->$field(\$key);",
1015             "my \@values = \$obj->$field([ qw(foo bar) ]);",
1016             "\$obj->$field(\%other_hash);",
1017             "\$obj->$field(foo => 23, bar => 42);",
1018             ],
1019             );
1020 1         554 my @clear_methods = uniq "clear_${field}", "${field}_clear";
1021 1         5 for my $name (@clear_methods) {
1022             $self->install_accessor(
1023             name => $name,
1024             code => sub {
1025 1 50 33 1   7 local $DB::sub = local *__ANON__ = "${class}::${name}"
        21      
        10      
1026             if defined &DB::DB && !$Devel::DProf::VERSION;
1027 1         5 %hash = ();
1028             },
1029 2         48 );
1030             }
1031             $self->document_accessor(
1032 1         34 name => \@clear_methods,
1033             purpose => <<'EODOC',
1034             Deletes all keys and values from the hash. Since this is a class variable, the
1035             value will be changed for all instances of this class.
1036             EODOC
1037             examples => ["\$obj->$clear_methods[0];"],
1038             );
1039 1         550 my @keys_methods = uniq "keys_${field}", "${field}_keys";
1040 1         4 for my $name (@keys_methods) {
1041             $self->install_accessor(
1042             name => $name,
1043             code => sub {
1044 3 50 33 4   14 local $DB::sub = local *__ANON__ = "${class}::${name}"
        5      
1045             if defined &DB::DB && !$Devel::DProf::VERSION;
1046 3         27 keys %hash;
1047             },
1048 2         40 );
1049             }
1050             $self->document_accessor(
1051 1         32 name => \@keys_methods,
1052             purpose => <<'EODOC',
1053             Returns a list of all hash keys in no particular order. Since this is a class
1054             variable, the value will be changed for all instances of this class.
1055             EODOC
1056             examples => ["my \@keys = \$obj->$keys_methods[0];"],
1057             belongs_to => $field,
1058             );
1059 1         585 my @values_methods = uniq "values_${field}", "${field}_values";
1060 1         5 for my $name (@values_methods) {
1061             $self->install_accessor(
1062             name => $name,
1063             code => sub {
1064 1 50 33 5   6 local $DB::sub = local *__ANON__ = "${class}::${name}"
1065             if defined &DB::DB && !$Devel::DProf::VERSION;
1066 1         9 values %hash;
1067             },
1068 2         45 );
1069             }
1070             $self->document_accessor(
1071 1         32 name => \@values_methods,
1072             purpose => <<'EODOC',
1073             Returns a list of all hash values in no particular order. Since this is a
1074             class variable, the value will be changed for all instances of this class.
1075             EODOC
1076             examples => ["my \@values = \$obj->$values_methods[0];"],
1077             belongs_to => $field,
1078             );
1079 1         527 my @exists_methods = uniq "exists_${field}", "${field}_exists";
1080 1         4 for my $name (@exists_methods) {
1081             $self->install_accessor(
1082             name => $name,
1083             code => sub {
1084 3 50 33 7   11 local $DB::sub = local *__ANON__ = "${class}::${name}"
1085             if defined &DB::DB && !$Devel::DProf::VERSION;
1086 3         18 exists $hash{ $_[1] };
1087             },
1088 2         39 );
1089             }
1090             $self->document_accessor(
1091 1         35 name => \@exists_methods,
1092             purpose => <<'EODOC',
1093             Takes a key and returns a true value if the key exists in the hash, and a
1094             false value otherwise. Since this is a class variable, the value will be
1095             changed for all instances of this class.
1096             EODOC
1097             examples => ["if (\$obj->$exists_methods[0](\$key)) { ... }"],
1098             belongs_to => $field,
1099             );
1100 1         688 my @delete_methods = uniq "delete_${field}", "${field}_delete";
1101 1         4 for my $name (@delete_methods) {
1102             $self->install_accessor(
1103             name => $name,
1104             code => sub {
1105 1 50 33 5   10 local $DB::sub = local *__ANON__ = "${class}::${name}"
1106             if defined &DB::DB && !$Devel::DProf::VERSION;
1107 1         4 my ($self, @keys) = @_;
1108 1         5 delete @hash{@keys};
1109             },
1110 2         42 );
1111             }
1112             $self->document_accessor(
1113 1         31 name => \@delete_methods,
1114             purpose => <<'EODOC',
1115             Takes a list of keys and deletes those keys from the hash. Since this is a
1116             class variable, the value will be changed for all instances of this class.
1117             EODOC
1118             examples => ["\$obj->$delete_methods[0](\@keys);"],
1119             belongs_to => $field,
1120             );
1121             }
1122 1         482 $self; # for chaining
1123             }
1124              
1125             sub mk_abstract_accessors {
1126 1     5 1 3 my ($self, @fields) = @_;
1127 1   33     11 my $class = ref $self || $self;
1128 1         3 for my $field (@fields) {
1129             $self->install_accessor(
1130             name => $field,
1131             code => sub {
1132 1 50 33 2   8 local $DB::sub = local *__ANON__ = "${class}::${field}"
1133             if defined &DB::DB && !$Devel::DProf::VERSION;
1134 1         3 my $method = "${class}::${field}";
1135 1         90 eval "require Error::Hierarchy::Internal::AbstractMethod";
1136 1 50       7 if ($@) {
1137              
1138             # Error::Hierarchy not installed?
1139 1         9 die sprintf "called abstract method [%s]", $method;
1140             } else {
1141              
1142             # need to pass method because caller() still doesn't see the
1143             # anonymously named sub's name
1144 0         0 throw Error::Hierarchy::Internal::AbstractMethod(
1145             method => $method,);
1146             }
1147             }
1148 1         76 );
1149             }
1150 1         31 $self; # for chaining
1151             }
1152              
1153             sub mk_boolean_accessors {
1154 0     0 1 0 my ($self, @fields) = @_;
1155 0   0     0 my $class = ref $self || $self;
1156 0         0 for my $field (@fields) {
1157             $self->install_accessor(
1158             name => $field,
1159             code => sub {
1160 0 0 0 0   0 local $DB::sub = local *__ANON__ = "${class}::${field}"
1161             if defined &DB::DB && !$Devel::DProf::VERSION;
1162 0 0       0 return $_[0]->{$field} if @_ == 1;
1163 0 0       0 $_[0]->{$field} = $_[1] ? 1 : 0; # normalize
1164             },
1165 0         0 );
1166 0         0 $self->document_accessor(
1167             name => $field,
1168             purpose => <<'EODOC',
1169             If called without an argument, returns the boolean value (0 or 1). If called
1170             with an argument, it normalizes it to the boolean value. That is, the values
1171             0, undef and the empty string become 0; everything else becomes 1.
1172             EODOC
1173             examples =>
1174             [ "\$obj->$field(\$value);", "my \$value = \$obj->$field;", ],
1175             );
1176 0         0 my @set_methods = uniq "set_${field}", "${field}_set";
1177 0         0 for my $name (@set_methods) {
1178             $self->install_accessor(
1179             name => $name,
1180             code => sub {
1181 0 0 0 0   0 local $DB::sub = local *__ANON__ = "${class}::${name}"
1182             if defined &DB::DB && !$Devel::DProf::VERSION;
1183 0         0 $_[0]->{$field} = 1;
1184             },
1185 0         0 );
1186             }
1187             $self->document_accessor(
1188 0         0 name => \@set_methods,
1189             purpose => 'Sets the boolean value to 1.',
1190             examples => ["\$obj->$set_methods[0];"],
1191             belongs_to => $field,
1192             );
1193 0         0 my @clear_methods = uniq "clear_${field}", "${field}_clear";
1194 0         0 for my $name (@clear_methods) {
1195             $self->install_accessor(
1196             name => $name,
1197             code => sub {
1198 0 0 0 0   0 local $DB::sub = local *__ANON__ = "${class}::${name}"
1199             if defined &DB::DB && !$Devel::DProf::VERSION;
1200 0         0 $_[0]->{$field} = 0;
1201             },
1202 0         0 );
1203             }
1204             $self->document_accessor(
1205 0         0 name => \@clear_methods,
1206             purpose => 'Clears the boolean value by setting it to 0.',
1207             examples => ["\$obj->$clear_methods[0];"],
1208             belongs_to => $field,
1209             );
1210             }
1211 0         0 $self; # for chaining
1212             }
1213              
1214             sub mk_integer_accessors {
1215 1     1 1 4 my ($self, @fields) = @_;
1216 1   33     9 my $class = ref $self || $self;
1217 1         3 for my $field (@fields) {
1218             $self->install_accessor(
1219             name => $field,
1220             code => sub {
1221 9 50 33 9   28 local $DB::sub = local *__ANON__ = "${class}::${field}"
        9      
        9      
1222             if defined &DB::DB && !$Devel::DProf::VERSION;
1223 9         33 my $self = shift;
1224 9 100 100     71 return $self->{$field} || 0 unless @_;
1225 2         8 $self->{$field} = shift;
1226             },
1227 2         458 );
1228 2         65 $self->document_accessor(
1229             name => $field,
1230             purpose => <<'EODOC',
1231             A basic getter/setter method. If called without an argument, it returns the
1232             value, or 0 if there is no previous value. If called with a single argument,
1233             it sets the value.
1234             EODOC
1235             examples =>
1236             [ "\$obj->$field(\$value);", "my \$value = \$obj->$field;", ],
1237             );
1238 2         989 my @reset_methods = uniq "reset_${field}", "${field}_reset";
1239 2         6 for my $name (@reset_methods) {
1240             $self->install_accessor(
1241             name => $name,
1242             code => sub {
1243 2 50 33 2   9 local $DB::sub = local *__ANON__ = "${class}::${name}"
        2      
        2      
        2      
1244             if defined &DB::DB && !$Devel::DProf::VERSION;
1245 2         6 $_[0]->{$field} = 0;
1246             },
1247 3         45 );
1248             }
1249             $self->document_accessor(
1250 2         61 name => \@reset_methods,
1251             purpose => 'Resets the value to 0.',
1252             examples => ["\$obj->$reset_methods[0];"],
1253             belongs_to => $field,
1254             );
1255 2         949 my @inc_methods = uniq "inc_${field}", "${field}_inc";
1256 2         6 for my $name (@inc_methods) {
1257             $self->install_accessor(
1258             name => $name,
1259             code => sub {
1260 2 50 33 2   10 local $DB::sub = local *__ANON__ = "${class}::${name}"
        2      
        2      
        2      
        2      
1261             if defined &DB::DB && !$Devel::DProf::VERSION;
1262 2         6 $_[0]->{$field}++;
1263             },
1264 4         73 );
1265             }
1266             $self->document_accessor(
1267 2         56 name => \@inc_methods,
1268             purpose => 'Increases the value by 1.',
1269             examples => ["\$obj->$inc_methods[0];"],
1270             belongs_to => $field,
1271             );
1272 2         985 my @dec_methods = uniq "dec_${field}", "${field}_dec";
1273 2         7 for my $name (@dec_methods) {
1274             $self->install_accessor(
1275             name => $name,
1276             code => sub {
1277 2 50 33 2   10 local $DB::sub = local *__ANON__ = "${class}::${name}"
        2      
        2      
        2      
        2      
1278             if defined &DB::DB && !$Devel::DProf::VERSION;
1279 2         6 $_[0]->{$field}--;
1280             },
1281 4         84 );
1282             }
1283             $self->document_accessor(
1284 2         56 name => \@dec_methods,
1285             purpose => 'Decreases the value by 1.',
1286             examples => ["\$obj->$dec_methods[0];"],
1287             belongs_to => $field,
1288             );
1289             }
1290 1         461 $self; # for chaining
1291             }
1292              
1293             sub mk_set_accessors {
1294 1     1 1 4 my ($self, @fields) = @_;
1295 1   33     9 my $class = ref $self || $self;
1296 1         4 for my $field (@fields) {
1297 1         3 my $insert_method = "${field}_insert";
1298 1         3 my $elements_method = "${field}_elements";
1299             $self->install_accessor(
1300             name => $field,
1301             code => sub {
1302 2 50 33 2   10 local $DB::sub = local *__ANON__ = "${class}::${field}"
1303             if defined &DB::DB && !$Devel::DProf::VERSION;
1304 2         4 my $self = shift;
1305 2 100       6 if (@_) {
1306 1         4 $self->$insert_method(@_);
1307             } else {
1308 1         4 $self->$elements_method;
1309             }
1310             },
1311 1         10 );
1312 1         35 $self->document_accessor(
1313             name => $field,
1314             purpose => <<'EODOC',
1315             A set is like an array except that each element can occur only one. It is,
1316             however, not ordered. If called with a list of arguments, it adds those
1317             elements to the set. If the first argument is an array reference, the values
1318             contained therein are added to the set. If called without arguments, it
1319             returns the elements of the set.
1320             EODOC
1321             examples => [
1322             "my \@elements = \$obj->$field;",
1323             "\$obj->$field(\@elements);",
1324             ],
1325             );
1326 1         658 my @insert_methods = uniq "insert_${field}", $insert_method;
1327 1         5 for my $name (@insert_methods) {
1328             $self->install_accessor(
1329             name => $name,
1330             code => sub {
1331 2 50 33 2   14 local $DB::sub = local *__ANON__ = "${class}::${name}"
1332             if defined &DB::DB && !$Devel::DProf::VERSION;
1333 2         4 my $self = shift;
1334 2         10 $self->{$field}{$_}++ for flatten(@_);
1335             },
1336 2         43 );
1337             }
1338             $self->document_accessor(
1339 1         33 name => \@insert_methods,
1340             purpose => <<'EODOC',
1341             If called with a list of arguments, it adds those elements to the set. If the
1342             first argument is an array reference, the values contained therein are added
1343             to the set.
1344             EODOC
1345             examples => ["\$obj->$insert_methods[0](\@elements);"],
1346             belongs_to => $field,
1347             );
1348 1         504 my @elements_methods = uniq "elements_${field}", $elements_method;
1349 1         5 for my $name (@elements_methods) {
1350             $self->install_accessor(
1351             name => $name,
1352             code => sub {
1353 4 50 33 6   15 local $DB::sub = local *__ANON__ = "${class}::${name}"
1354             if defined &DB::DB && !$Devel::DProf::VERSION;
1355 4         14 my $self = shift;
1356 4   100     32 $self->{$field} ||= {};
1357 4         5 keys %{ $self->{$field} };
  4         43  
1358             },
1359 2         43 );
1360             }
1361             $self->document_accessor(
1362 1         69 name => \@elements_methods,
1363             purpose => 'Returns the elements of the set.',
1364             examples => ["my \@elements = \$obj->$elements_methods[0];"],
1365             belongs_to => $field,
1366             );
1367 1         507 my @delete_methods = uniq "delete_${field}", "${field}_delete";
1368 1         3 for my $name (@delete_methods) {
1369             $self->install_accessor(
1370             name => $name,
1371             code => sub {
1372 1 50 33 7   6 local $DB::sub = local *__ANON__ = "${class}::${name}"
1373             if defined &DB::DB && !$Devel::DProf::VERSION;
1374 1         3 my $self = shift;
1375 1         7 delete $self->{$field}{$_} for @_;
1376             },
1377 2         42 );
1378             }
1379             $self->document_accessor(
1380 1         36 name => \@delete_methods,
1381             purpose => <<'EODOC',
1382             If called with a list of values, it deletes those elements from the set.
1383             EODOC
1384             examples => ["\$obj->$delete_methods[0](\@elements);"],
1385             belongs_to => $field,
1386             );
1387 1         582 my @clear_methods = uniq "clear_${field}", "${field}_clear";
1388 1         4 for my $name (@clear_methods) {
1389             $self->install_accessor(
1390             name => $name,
1391             code => sub {
1392 1 50 33 6   7 local $DB::sub = local *__ANON__ = "${class}::${name}"
1393             if defined &DB::DB && !$Devel::DProf::VERSION;
1394 1         5 $_[0]->{$field} = {};
1395             },
1396 2         42 );
1397             }
1398             $self->document_accessor(
1399 1         34 name => \@clear_methods,
1400             purpose => 'Deletes all elements from the set.',
1401             examples => ["\$obj->$clear_methods[0];"],
1402             belongs_to => $field,
1403             );
1404 1         595 my @contains_methods = uniq "contains_${field}", "${field}_contains";
1405 1         5 for my $name (@contains_methods) {
1406             $self->install_accessor(
1407             name => $name,
1408             code => sub {
1409 4 50 33 6   16 local $DB::sub = local *__ANON__ = "${class}::${name}"
1410             if defined &DB::DB && !$Devel::DProf::VERSION;
1411 4         8 my ($self, $key) = @_;
1412 4 50       11 return unless defined $key;
1413 4         34 exists $self->{$field}{$key};
1414             },
1415 2         41 );
1416             }
1417             $self->document_accessor(
1418 1         30 name => \@contains_methods,
1419             purpose => <<'EODOC',
1420             Takes a single key and returns a boolean value indicating whether that key is
1421             an element of the set.
1422             EODOC
1423             examples => ["if (\$obj->$contains_methods[0](\$element)) { ... }"],
1424             ,
1425             belongs_to => $field,
1426             );
1427 1         444 my @is_empty_methods = uniq "is_empty_${field}", "${field}_is_empty";
1428 1         23 for my $name (@is_empty_methods) {
1429             $self->install_accessor(
1430             name => $name,
1431             code => sub {
1432 2 50 33 7   569 local $DB::sub = local *__ANON__ = "${class}::${name}"
1433             if defined &DB::DB && !$Devel::DProf::VERSION;
1434 2         5 my $self = shift;
1435 2 50       4 keys %{ $self->{$field} || {} } == 0;
  2         20  
1436             },
1437 2         38 );
1438             }
1439             $self->document_accessor(
1440 1         30 name => \@is_empty_methods,
1441             purpose =>
1442             'Returns a boolean value indicating whether the set is empty of not.',
1443             examples => ["\$obj->$is_empty_methods[0];"],
1444             belongs_to => $field,
1445             );
1446 1         523 my @size_methods = uniq "size_${field}", "${field}_size";
1447 1         4 for my $name (@size_methods) {
1448             $self->install_accessor(
1449             name => $name,
1450             code => sub {
1451 4 50 33 10   16 local $DB::sub = local *__ANON__ = "${class}::${name}"
1452             if defined &DB::DB && !$Devel::DProf::VERSION;
1453 4         6 my $self = shift;
1454 4 50       5 scalar keys %{ $self->{$field} || {} };
  4         28  
1455             },
1456 2         38 );
1457             }
1458             $self->document_accessor(
1459 1         28 name => \@size_methods,
1460             purpose => 'Returns the number of elements in the set.',
1461             examples => ["my \$size = \$obj->$size_methods[0];"],
1462             belongs_to => $field,
1463             );
1464             }
1465 1         435 $self; # for chaining
1466             }
1467              
1468             sub mk_object_accessors {
1469 2     8 1 10 my ($self, @args) = @_;
1470 2   33     18 my $class = ref $self || $self;
1471 2         8 while (@args) {
1472 3         466 my $type = shift @args;
1473 3 50       13 my $list = shift @args or die "No slot names for $class";
1474              
1475             # Allow a list of hashrefs.
1476 3 50       53 my @list = ref($list) eq 'ARRAY' ? @$list : ($list);
1477 3         8 for my $obj_def (@list) {
1478 3         3 my ($name, @composites);
1479 3 100       10 if (!ref $obj_def) {
1480 2         3 $name = $obj_def;
1481             } else {
1482 1         4 $name = $obj_def->{slot};
1483 1         2 my $composites = $obj_def->{comp_mthds};
1484 1 0       6 @composites =
    50          
1485             ref($composites) eq 'ARRAY' ? @$composites
1486             : defined $composites ? ($composites)
1487             : ();
1488             }
1489 3         8 for my $meth (@composites) {
1490             $self->install_accessor(
1491             name => $meth,
1492             code => sub {
1493 1 50 33 5   7 local $DB::sub = local *__ANON__ = "${class}::{$meth}"
1494             if defined &DB::DB && !$Devel::DProf::VERSION;
1495 1         2 my ($self, @args) = @_;
1496 1         4 $self->$name()->$meth(@args);
1497             },
1498 2         475 );
1499 2         68 $self->document_accessor(
1500             name => $meth,
1501             purpose => <
1502             Calls $meth() with the given arguments on the object stored in the $name slot.
1503             If there is no such object, a new $type object is constructed - no arguments
1504             are passed to the constructor - and stored in the $name slot before forwarding
1505             $meth() onto it.
1506             EODOC
1507             examples => [ "\$obj->$meth(\@args);", "\$obj->$meth;", ],
1508             );
1509             }
1510             $self->install_accessor(
1511             name => $name,
1512             code => sub {
1513 12 50 33 13   1010 local $DB::sub = local *__ANON__ = "${class}::${name}"
1514             if defined &DB::DB && !$Devel::DProf::VERSION;
1515 12         56 my ($self, @args) = @_;
1516 12 50 33     38 if (ref($args[0]) && UNIVERSAL::isa($args[0], $type)) {
1517 0         0 $self->{$name} = $args[0];
1518             } else {
1519 12 100       56 defined $self->{$name}
1520             or $self->{$name} = $type->new(@args);
1521             }
1522 12         57 $self->{$name};
1523             },
1524 3         492 );
1525 3         108 $self->document_accessor(
1526             name => $name,
1527             purpose => <
1528             If called with an argument object of type $type it sets the object; further
1529             arguments are discarded. If called with arguments but the first argument is
1530             not an object of type $type, a new object of type $type is constructed and the
1531             arguments are passed to the constructor.
1532              
1533             If called without arguments, it returns the $type object stored in this slot;
1534             if there is no such object, a new $type object is constructed - no arguments
1535             are passed to the constructor in this case - and stored in the $name slot
1536             before returning it.
1537             EODOC
1538             examples => [
1539             "my \$object = \$obj->$name;", "\$obj->$name(\$object);",
1540             "\$obj->$name(\@args);",
1541             ],
1542             );
1543 3         1326 my @clear_methods = uniq "clear_${name}", "${name}_clear";
1544 3         12 for my $meth (@clear_methods) {
1545             $self->install_accessor(
1546             name => $meth,
1547             code => sub {
1548 0 0 0 13   0 local $DB::sub = local *__ANON__ = "${class}::${meth}"
1549             if defined &DB::DB && !$Devel::DProf::VERSION;
1550 0         0 delete $_[0]->{$name};
1551             },
1552 6         147 );
1553             }
1554             $self->document_accessor(
1555 3         101 name => \@clear_methods,
1556             purpose => 'Deletes the object.',
1557             examples => "\$obj->$clear_methods[0];",
1558             belongs_to => $name,
1559             );
1560             }
1561             }
1562 2         864 $self; # for chaining
1563             }
1564              
1565             sub mk_forward_accessors {
1566 1     10 1 4 my ($self, %args) = @_;
1567 1   33     6 my $class = ref $self || $self;
1568 1         6 while (my ($slot, $methods) = each %args) {
1569 2 100       420 my @methods = ref $methods eq 'ARRAY' ? @$methods : ($methods);
1570 2         3 for my $field (@methods) {
1571             $self->install_accessor(
1572             name => $field,
1573             code => sub {
1574 3 50 33 3   19 local $DB::sub = local *__ANON__ = "${class}::${field}"
1575             if defined &DB::DB && !$Devel::DProf::VERSION;
1576 3         6 my ($self, @args) = @_;
1577 3         7 $self->$slot()->$field(@args);
1578             },
1579 3         422 );
1580 3         79 $self->document_accessor(
1581             name => $field,
1582             purpose => <
1583             Calls $field() with the given arguments on the object stored in the $slot
1584             slot.
1585             EODOC
1586             examples => [ "\$obj->$field(\@args);", "\$obj->$field;", ],
1587             );
1588             }
1589             }
1590 1         412 $self; # for chaining
1591             }
1592             1;
1593              
1594              
1595             __END__