File Coverage

blib/lib/Class/Methodist.pm
Criterion Covered Total %
statement 308 327 94.1
branch 77 94 81.9
condition 7 9 77.7
subroutine 59 64 92.1
pod 2 13 15.3
total 453 507 89.3


line stmt bran cond sub pod time code
1             package Class::Methodist;
2              
3 9     9   7088 use strict;
  9         15  
  9         283  
4 9     9   46 use warnings;
  9         13  
  9         223  
5 9     9   46 use Carp;
  9         19  
  9         5948  
6              
7             =head1 NAME
8              
9             Class::Methodist - define methods for instance variables in a class
10              
11             =head1 SYNOPSIS
12              
13             package My::Shiny::New::Class;
14              
15             use Class::Methodist
16             (
17             scalar => 'global_config_path',
18             hash => 'unique_words',
19             list => 'file_names',
20             object => { name => 'thing', class => 'My::Thing:Class' },
21             enum => { name => 'color', domain => [ 'red', 'green', 'blue' ] },
22             scalars => [ 'alpha', 'beta' ]
23             );
24              
25             sub new {
26             my ($class, $alpha) = @_;
27             $class->beget(alpha => $alpha, beta => 42);
28             }
29              
30             =head1 DESCRIPTION
31              
32             This package creates instance variables and methods on a class for
33             accessing and manipulating those instance variables.
34             C is similar in spirit to C, but
35             with a simpler interface and more sensible semantics.
36              
37             Instance variables to be defined are given as a list of I
38             variable specifications> (a.k.a. I) when the module is
39             used. A specification consists of a pair whose first element is the
40             I of the variable (e.g., C, C, C) and whose
41             second element is the I of the variable to be defined. The
42             latter must be a valid Perl identifier name.
43              
44             For each specification, the module defines a type-specific set of
45             methods on the calling class. The names of these methods usually
46             include the name of the instance variable. In the following sections,
47             we refer to the instance variable name by the generic identifier
48             I.
49              
50             In your constructor you must call the C class method to
51             instantiate and initialize each instance of the class.
52              
53             =head1 CLASS METHODS
54              
55             =over
56              
57             =item beget()
58              
59             This class method instantiates and initializes an object of the class.
60             It takes the place of an explicit call to the Perl C function
61             (which it invokes under the hood).
62              
63             You may pass arguments to C to initialize the new object.
64             These arguments must appear in pairs (as for a hash initializer). The
65             first item in each pair should be the name of an attribute defined by
66             your use of C and the second item in each pair
67             should be the value to which that attribute is initialized. Note that
68             if you initialize I or I attributes, you must pass the
69             initializer value as a I to an array or hash, respectively.
70              
71             The C method blesses the new object into the class and returns
72             the blessed object. You can either assign the return value to a
73             variable (often, C) for further construction, or may simply
74             invoke C as the final statement in your constructor, which
75             arranges to return the newly minted object to the caller.
76              
77             =item import()
78              
79             This method satisfies the C semantics required of any module
80             that uses C. It takes as arguments the list of
81             specifications provided in the C directive in the calling module.
82             The method defines the instance variables and their associated methods
83             in the namespace of the I, also referred to as the
84             I.
85              
86             =cut
87              
88             sub import {
89 12     12   3516 my ($my_class, @args) = @_;
90 12         125 my $dest_class = caller; # Caller's class for importing methods.
91              
92 12         79 while (my ($type, $spec) = splice(@args, 0, 2)) {
93             SWITCH:
94 31         61 for ($type) {
95 31 100       106 /ctor/ and do {
96 10         49 define_constructor($dest_class, $spec);
97 10         64 last SWITCH;
98             };
99              
100 21 100       68 /enum/ and do {
101 2         5 define_enum_methods($dest_class, $spec);
102 2         8 last SWITCH;
103             };
104              
105 19 100       60 /hash$/ and do {
106 4         13 define_hash_methods($dest_class, $spec);
107 4         17 last SWITCH;
108             };
109              
110 15 100       41 /hash_of_lists/ and do {
111 1         5 define_hash_of_lists_methods($dest_class, $spec);
112 1         5 last SWITCH;
113             };
114              
115 14 100       39 /list/ and do {
116 4         16 define_list_methods($dest_class, $spec);
117 4         20 last SWITCH;
118             };
119              
120 10 100       35 /object/ and do {
121 5         13 define_object_methods($dest_class, $spec);
122 5         22 last SWITCH;
123             };
124              
125 5 50       25 /scalar$/ and do {
126 5         15 define_scalar_methods($dest_class, $spec);
127 5         25 last SWITCH;
128             };
129              
130 0 0       0 /scalars/ and do {
131 0         0 define_scalar_methods($dest_class, $_) foreach @$spec;
132 0         0 last SWITCH;
133             };
134              
135 0         0 confess "Invalid type '$type'";
136             }
137             }
138              
139 12         37 define_utility_methods($dest_class);
140             }
141              
142             #----------------------------------------------------------------
143              
144             =item verify_method_not_defined($dest_class, $method)
145              
146             We don't want to overwrite methods already defined in the calling
147             class. Check whether C<$method> is defined in the destination class.
148             If so, throw an exception.
149              
150             =cut
151              
152             sub verify_method_not_defined {
153 0     0 1 0 my ($dest_class, $method) = @_;
154              
155 9     9   57 use Devel::Symdump;
  9         18  
  9         1333  
156 0         0 my @functions = Devel::Symdump->new($dest_class)->functions();
157              
158 0 0       0 if (grep { $_ eq $method } @functions) {
  0         0  
159 0         0 confess "Method '$method' already exists in class '$dest_class'";
160             }
161             }
162              
163             #----------------------------------------------------------------
164              
165             =item define_method($dest_class, $method, $sub_ref)
166              
167             Define a method named C<$method> in the destination class
168             C<$dest_class> to be the subroutine refererenced by C<$sub_ref>. It
169             is an error to define a method that already exists. This method is
170             the business end of this module in that all the following
171             type-specific methods invoke C in order to create the
172             method(s) associated with each instance variable.
173              
174             =back
175              
176             =cut
177              
178             sub define_method {
179 197     197 1 287 my ($dest_class, $method, $sub_ref) = @_;
180              
181             # Try turning this off for now. Called a *lot*. May not be of much
182             # benefit.
183             #
184             # verify_method_not_defined($dest_class, $method);
185              
186 197         504 my $fq_name = sprintf('%s::%s', $dest_class, $method);
187             {
188 9     9   50 no strict 'refs';
  9         13  
  9         29170  
  197         202  
189 197         463 *{$fq_name} = $sub_ref;
  197         1593  
190             }
191             }
192              
193             #----------------------------------------------------------------
194              
195             {
196             my %methodist_info;
197              
198             ## Return whether the named class has Methodist-internal data. This
199             ## subroutine was added to allow us to handle properly inheritance
200             ## from classes that don't use Methodist (e.g., Class::Singleton).
201             sub _has_methodist_info {
202 22     22   35 my $dest_class = shift;
203 22         89 exists $methodist_info{$dest_class};
204             }
205              
206             ## Add @values to the list stored under $key in the Methodist-internal
207             ## data for this class.
208             sub _add_methodist_info {
209 18     18   40 my ($dest_class, $key, @values) = @_;
210 18         24 push @{$methodist_info{$dest_class}{$key}}, @values;
  18         65  
211             }
212              
213             ## Return the list of values stored under $key in the
214             ## Methodist-internal data for this class. If no data are stored
215             ## under that key, return an empty list.
216             sub _get_methodist_info {
217 30     30   49 my ($dest_class, $key) = @_;
218 30   100     109 $methodist_info{$dest_class}{$key} ||= [ ];
219 30         38 return @{$methodist_info{$dest_class}{$key}};
  30         102  
220             }
221             }
222              
223             #----------------------------------------------------------------
224              
225             =head2 Constructor
226              
227             Define a constructor in the destination class as follows:
228              
229             ctor => 'new'
230              
231             The generated constructor simply blesses an anonymous hash into the
232             destination class.
233              
234             =cut
235              
236             sub define_constructor {
237 10     10 0 22 my ($dest_class, $name) = @_;
238              
239             ## Bless a hash reference into the destination class.
240             define_method($dest_class, $name,
241             sub {
242 15     15   3965 $dest_class->beget();
243 10         72 });
244             }
245              
246             #----------------------------------------------------------------
247              
248             =head2 Enum
249              
250             Define methods in the destination class for a scalar-valued instance
251             variable that is constrained to take one of an enumerated series of
252             values.
253              
254             enum => { name => 'colors',
255             domain => [ qw/red green blue/ ],
256             default => 'blue' }
257              
258             The C and C attributes are required. If the C
259             attribute is provided, its value must evaluate to a member of the
260             domain.
261              
262             =over
263              
264             =cut
265              
266             sub define_enum_methods {
267 2     2 0 3 my ($dest_class, $spec) = @_;
268              
269 2         3 my $name = $spec->{name};
270 2         3 my @domain = @{$spec->{domain}};
  2         5  
271              
272 2         6 _add_methodist_info($dest_class, attributes => [ enum => $name ]);
273              
274 2 100       6 if (defined $spec->{default}) {
275 1 50       16 croak sprintf("Default (%s) not among %s",
276             $spec->{default}, join(', ', @domain))
277             unless (grep(/$spec->{default}/, @domain));
278 1         3 _add_methodist_info($dest_class,
279             default => [ $name => $spec->{default} ]);
280             }
281              
282             =item I(...)
283              
284             The method named the same as the instance variable is the setter and
285             getter. If called with no arguments, returns the current value of the
286             enumerated attribute. If called with an argument, the scalar is set
287             to that value, provided the value is one of the values enumerated in
288             the C list. If the value is not in the domain, throws an
289             error.
290              
291             =back
292              
293             =cut
294              
295             define_method($dest_class, $name,
296             sub {
297 24     24   6980 my ($self, $arg) = @_;
298 24 100       63 if (defined($arg)) {
299 12 100       269 if (grep(/$arg/, @domain)) {
300 10         23 $self->{$name} = $arg;
301             } else {
302 2         47 croak sprintf("%s not among %s",
303             $arg, join(', ', @domain));
304             }
305             }
306 22         121 $self->{$name};
307 2         11 });
308             }
309              
310             #----------------------------------------------------------------
311              
312             =head2 Hash
313              
314             Define methods in the destination class for a hash-valued instance
315             variable called I as follows:
316              
317             hash => 'inst_var'
318              
319             This specification defines the following methods in the destination
320             class:
321              
322             =over
323              
324             =cut
325              
326             sub define_hash_methods {
327 4     4 0 8 my ($dest_class, $name) = @_;
328              
329 4         12 _add_methodist_info($dest_class, attributes => [ hash => $name ]);
330              
331             =item I($key, [$value])
332              
333             The method having the same name as the instance variable is the setter
334             and getter:
335              
336             my $value = $obj->inst_var('key');
337             $obj->inst_var(key => 'value');
338              
339             When called with a single argument, there are two cases. First, if
340             the argument is a hash reference, replace the contents of the hash
341             with that of the referenced hash. Second, if it is not a hash
342             reference, treat it as a key; the method returns the value stored
343             under that key.
344              
345             When called with more than one argument, treat the arguments as
346             key-value pairs and store them in the hash. There must be an even
347             number of arguments (i.e., they must be pairs). Return the value of
348             the last pair.
349              
350             =cut
351              
352             define_method($dest_class, $name,
353             sub {
354 13     13   38 my ($self, @args) = @_;
355 13         15 my $rtn = undef;
356              
357 13 100       25 if (@args == 1) {
358 8 100       19 if (ref $args[0] eq 'HASH') {
359 1         3 $self->{$name} = $args[0];
360             } else {
361 7         16 $rtn = $self->{$name}{$args[0]};
362             }
363             } else {
364 5         20 while (my ($key, $val) = splice(@args, 0, 2)) {
365 8         33 $rtn = $self->{$name}{$key} = $val;
366             }
367             }
368 13         48 return $rtn;
369 4         25 });
370              
371             =item I_exists($key)
372              
373             Method that returns whether a key exists in the hash.
374              
375             if ($obj->inst_var_exists('key')) { ... }
376              
377             =cut
378              
379             define_method($dest_class, "${name}_exists",
380             sub {
381 5     5   2749 my ($self, $key) = @_;
382 5 50       20 confess "Must supply key" unless defined $key;
383 5 100       31 exists $self->{$name}{$key} ? 1 : undef;
384 4         22 });
385              
386             =item I_keys()
387              
388             Method that returns the list of keys in the hash.
389              
390             my @keys = $obj->inst_var_keys();
391              
392             =cut
393              
394             define_method($dest_class, "${name}_keys",
395             sub {
396 2     2   4 my $self = shift;
397 2         3 sort keys %{$self->{$name}};
  2         15  
398 4         46 });
399              
400             =item I_values()
401              
402             Method that returns the list of values in the hash.
403              
404             my @values = $obj->inst_var_values();
405              
406             =cut
407              
408             define_method($dest_class, "${name}_values",
409             sub {
410 2     2   1014 my $self = shift;
411 2         2 sort values %{$self->{$name}}
  2         10  
412 4         18 });
413              
414             =item I_clear()
415              
416             Method that clears the hash.
417              
418             $obj->inst_var_clear();
419              
420             =cut
421              
422             define_method($dest_class, "${name}_clear",
423             sub {
424 3     3   422 my $self = shift;
425 3         7 $self->{$name} = { };
426 4         18 });
427              
428             =item I_delete($key)
429              
430             Delete the hash element with the given key.
431              
432             $obj->inst_var_delete($key)
433              
434             =cut
435              
436             define_method($dest_class, "${name}_delete",
437             sub {
438 0     0   0 my ($self, $key) = @_;
439 0         0 delete $self->{$name}{$key};
440 4         22 });
441              
442             =item I_size()
443              
444             Return the number of key-value pairs stored in the hash.
445              
446             my $size = inst_var_size();
447              
448             =cut
449              
450             define_method($dest_class, "${name}_size",
451             sub {
452 2     2   458 my $self = shift;
453 2         3 scalar keys %{$self->{$name}};
  2         12  
454 4         19 });
455              
456             =item I_inc($key, [$n])
457              
458             Add the value of C<$n> to the value found under C<$key> in the hash.
459             The value of C<$n> defaults to one, yielding a simple increment
460             operation. Return the new value.
461              
462             =back
463              
464             =cut
465              
466             define_method($dest_class, "${name}_inc",
467             sub {
468 3     3   11 my ($self, $key, $n) = @_;
469 3 50       9 $n = 1 unless defined $n;
470 3         12 $self->{$name}{$key} += $n;
471 4         36 });
472             }
473              
474             #----------------------------------------------------------------
475              
476             =head2 Hash of Lists
477              
478             Define methods in the destination class for a hash-of-lists instance
479             variable called I as follows:
480              
481             hash_of_lists => 'inst_var'
482              
483             This specification defines the following methods in the destination
484             class:
485              
486             =over
487              
488             =cut
489              
490             sub define_hash_of_lists_methods {
491 1     1 0 2 my ($dest_class, $name) = @_;
492              
493 1         5 _add_methodist_info($dest_class, attributes => [ hash => $name ]);
494              
495             =item I(...)
496              
497             The method having the same name as the instance variable is the setter
498             and getter. Its behavior depends on the number of arguments passed to
499             the method.
500              
501             When called with no arguments, the method returns all the values
502             stored in all the lists.
503              
504             When called with one argument, it is treated as a key into the hash
505             and returns the values stored in the list having that hash key.
506              
507             The method returns a list in array context and a reference to a list
508             in scalar context.
509              
510             =cut
511              
512             define_method($dest_class, $name,
513             sub {
514 4     4   1881 my ($self, @args) = @_;
515              
516 4         14 my @rtn;
517 4 100       13 if (@args == 0) {
    100          
518             # Called with no arguments. Return all the values
519             # stored in all the lists.
520 1         3 push @rtn, @$_ foreach values %{$self->{$name}};
  1         8  
521             } elsif (@args == 1) {
522             # Called with one argument. Return all the values
523             # stored in the list having that value as a key
524 2         3 my $key = $args[0];
525 2 50       8 $self->{$name}{$key} = [ ]
526             unless defined $self->{$name}{$key};
527 2         4 @rtn = @{$self->{$name}{$key}};
  2         6  
528             } else {
529 1         23 confess "Must have zero or one arguments";
530             }
531              
532             # Return values as a list in list context and as a
533             # list reference in scalar context.
534 3 50       7 if (wantarray) {
535 3         14 return @rtn;
536             } else {
537 0         0 return \@rtn;
538             }
539 1         6 });
540              
541             =item I_push($key, @args)
542              
543             Push C<@args> on the list stored under C<$key>.
544              
545             =cut
546              
547             define_method($dest_class, "${name}_push",
548             sub {
549 7     7   2511 my ($self, $key, @args) = @_;
550 7         8 push @{$self->{$name}{$key}}, @args;
  7         19  
551 1         7 });
552              
553             =item I_keys()
554              
555             Return a list of all the keys in the hash.
556              
557             =back
558              
559             =cut
560              
561             define_method($dest_class, "${name}_keys",
562             sub {
563 1     1   575 my $self = shift;
564 1         3 keys %{$self->{$name}};
  1         6  
565 1         5 });
566             }
567              
568             #----------------------------------------------------------------
569              
570             =head2 List
571              
572             Define methods in the destination class for a list-valued instance
573             variable called I as follows:
574              
575             list => 'inst_var'
576              
577             This specification defines the following methods in the destination
578             class:
579              
580             =over
581              
582             =cut
583              
584             sub define_list_methods {
585 4     4 0 8 my ($dest_class, $name) = @_;
586              
587 4         17 _add_methodist_info($dest_class, attributes => [ list => $name ]);
588              
589             =item I(...)
590              
591             The method named the same as the instance variable is the setter and
592             getter. Its behavior depends on the number of arguments with which it
593             is invoked.
594              
595             When called with no arguments, return the contents of the list (when
596             called in array context) or a reference to the list (when called in
597             scalar context).
598              
599             When called with one argument that is a I to a list,
600             I the contents of the list with the contents of the
601             referenced list. Otherwise, I the contents of the list with
602             the arguments.
603              
604             =cut
605              
606             define_method($dest_class, $name,
607             sub {
608 29     29   4041 my ($self, @args) = @_;
609              
610 29 100 100     100 if (@args == 0) {
    100          
611             # Called without arguments. Return the contents
612             # of the list. as a list in list context and as a
613             # list reference in scalar context.
614 16 100       25 if (wantarray) {
615 12         14 return @{$self->{$name}};
  12         62  
616             } else {
617 4         13 return $self->{$name};
618             }
619             } elsif (@args == 1 and ref $args[0] eq 'ARRAY') {
620             # Called with reference to a list. Replace the
621             # contents of the list with the elements
622             # referenced.
623 1         3 $self->{$name} = $args[0];
624             } else {
625             ## Called with multiple arguments. Replace the
626             ## contents of the list with those arguments
627 12         36 $self->{$name} = \@args;
628             }
629 4         31 });
630              
631             =item push_I(@args)
632              
633             Given a list of values, push them on to the end of the list. Return
634             the new number of list elements.
635              
636             =cut
637              
638             define_method($dest_class, "push_$name",
639             sub {
640 3     3   658 my ($self, @args) = @_;
641 3         7 push @{$self->{$name}}, @args;
  3         9  
642 3         5 scalar @{$self->{$name}};
  3         9  
643 4         35 });
644              
645             =item push_I_if_new(@args)
646              
647             Given a list of values, push them on to the end of the list unless
648             they already exist on he list. Returns the new number of list
649             elements. Note that this method uses Perl's C function and so
650             is only suitable for short lists.
651              
652             =cut
653              
654             define_method($dest_class, "push_${name}_if_new",
655             sub {
656 9     9   3746 my ($self, @args) = @_;
657 9         16 foreach my $arg (@args) {
658 6         21 push @{$self->{$name}}, $arg
  10         46  
659 10 100       10 unless grep($_ eq $arg, @{$self->{$name}});
660             }
661 9         11 scalar @{$self->{$name}};
  9         49  
662 4         40 });
663              
664             =item pop_I
665              
666             Pop a single value from the end of the list and return it.
667              
668             =cut
669              
670             define_method($dest_class, "pop_$name",
671             sub {
672 3     3   637 my $self = shift;
673 3         6 pop @{$self->{$name}};
  3         9  
674 4         36 });
675              
676             =item unshift_I(@args)
677              
678             Given a list of values, unshift them on to the front of the list.
679             Return the new number of list elements.
680              
681             =cut
682              
683             define_method($dest_class, "unshift_$name",
684             sub {
685 1     1   2 my ($self, @args) = @_;
686 1         4 unshift @{$self->{$name}}, @args;
  1         3  
687 1         2 scalar @{$self->{$name}};
  1         3  
688 4         112 });
689              
690             =item shift_I()
691              
692             Shift a single value from the front of the list and return it.
693              
694             =cut
695              
696             define_method($dest_class, "shift_$name",
697             sub {
698 4     4   454 my $self = shift;
699 4         5 shift @{$self->{$name}};
  4         18  
700 4         25 });
701              
702             =item first_of_I()
703              
704             Return (but do not remove) the first element in the list. If the list
705             is empty, return undef.
706              
707             =cut
708              
709             define_method($dest_class, "first_of_$name",
710             sub {
711 3     3   4 my $self = shift;
712 3 100       5 @{$self->{$name}} ? $self->{$name}[0] : undef;
  3         17  
713 4         21 });
714              
715             =item last_of_I()
716              
717             Return (but do not remove) the last element in the list. If the list
718             is empty, return undef.
719              
720             =cut
721              
722             define_method($dest_class, "last_of_$name",
723             sub {
724 3     3   4 my $self = shift;
725 3 100       3 @{$self->{$name}} ? $self->{$name}[-1] : undef;
  3         16  
726 4         23 });
727              
728             =item count_I()
729              
730             Return the number of elements currently on the list.
731              
732             =cut
733              
734             define_method($dest_class, "count_$name",
735             sub {
736 14     14   2567 my $self = shift;
737 14         16 scalar @{$self->{$name}};
  14         59  
738 4         22 });
739              
740             =item clear_I()
741              
742             Delete the contents of the list.
743              
744             =cut
745              
746             define_method($dest_class, "clear_$name",
747             sub {
748 5     5   488 my $self = shift;
749 5         14 $self->{$name} = [ ];
750 4         30 });
751              
752             =item join_I([$glue])
753              
754             Return the join of the list. The list is not modified. If C<$glue>
755             is defined, join the list with the given glue. Otherwise, join the
756             list with the empty string.
757              
758             =cut
759              
760             define_method($dest_class, "join_$name",
761             sub {
762 12     12   31 my ($self, $glue) = @_;
763 12 100       28 $glue = '' unless defined $glue;
764 12         51 join($glue, @{$self->{$name}});
  12         61  
765 4         23 });
766              
767             =item grep_I($re)
768              
769             Return the list generated by grepping the list against C<$re>, which
770             must be a compiled regular express (usually using C).
771              
772             =back
773              
774             =cut
775              
776             define_method($dest_class, "grep_$name",
777             sub {
778 5     5   2313 my ($self, $re) = @_;
779 5         6 grep(/$re/, @{$self->{$name}});
  5         58  
780 4         32 });
781             }
782              
783             #----------------------------------------------------------------
784              
785             =head2 Object
786              
787             Define methods in the destination class for an object-valued instance
788             variable called I.
789              
790             For specifications of this form (scalar-valued):
791              
792             object => 'inst_var'
793              
794             the scalar is used as the name of the instance variable.
795              
796             For specifications of this form (hash-reference-valued), the instance
797             variable is defined by attribute-value pairs in the referenced hash:
798              
799             object => { name => 'inst_var',
800             class => 'Class::Name',
801             delegate => [ 'method1', 'method2' ] }
802              
803             The I C attribute gives the name of the instance
804             variable.
805              
806             The I C attribute gives the name of the class (or one
807             of its superclasses) whose objects can be assigned to this instance
808             variable. Attempting to set the instance variable to instances of
809             other classes throws an exception.
810              
811             The I C attribute takes a reference to a list of
812             method names. These methods are defined in the destination class as
813             methods that invoke the identically-named methods on the object
814             referenced by the instance variable.
815              
816             This specification defines the following methods in the destination
817             class:
818              
819             =over
820              
821             =cut
822              
823             sub define_object_methods {
824 5     5 0 7 my ($dest_class, $spec) = @_;
825              
826 5         6 my $name = undef;
827 5         6 my $required_class = undef;
828 5         7 my @delegate;
829              
830 5 100       13 if (ref($spec) eq 'HASH') {
831 3         7 $name = $spec->{name};
832 3         5 $required_class = $spec->{class};
833 3 100       10 @delegate = @{$spec->{delegate}} if exists $spec->{delegate};
  1         3  
834             } else {
835 2         4 $name = $spec;
836             }
837              
838 5 50       13 confess "No name specified" unless defined $name;
839              
840             =item I(...)
841              
842             The method named the same as the instance variable is its getter and
843             setter. When called with an argument, the instance variable is set to
844             that value. If the specification includes a C attribute, the
845             argument must be an object of that class or its subclasses (tested
846             using Perl's C built-in). Returns the value of the instance
847             variable (which may have just been set).
848              
849             =cut
850              
851             define_method($dest_class, $name,
852             sub {
853 12     12   3256 my ($self, $arg) = @_;
854              
855 12 100       34 if (defined $arg) {
856             # Called with an argument.
857 7 50       21 confess "Must pass an object as value" unless ref $arg;
858 7 100       16 if ($required_class) {
859             # The 'class' attribute was supplied; the
860             # argument must be of the specified class.
861 4         7 my $arg_class = ref $arg;
862 4 100       53 confess "Requires '$required_class', not '$arg_class'"
863             unless $arg->isa($required_class);
864             }
865             # Assign the value to the argument.
866 6         25 $self->{$name} = $arg;
867             }
868              
869             # Return the current object (whether arguments or not).
870 11         40 $self->{$name};
871 5         24 });
872              
873             # Created delegates, if any.
874 5         10 foreach my $delegate (@delegate) {
875             define_method($dest_class, $delegate,
876             sub {
877 2     2   628 my ($self, @args) = @_;
878 2         11 $self->{$name}->$delegate(@args);
879 2         11 });
880             }
881              
882             =item clear_I()
883              
884             Undefine the object instance variable. This method is so named to
885             make it consistent with other methods defined by this module.
886              
887             =back
888              
889             =cut
890              
891             define_method($dest_class, "clear_$name",
892             sub {
893 1     1   333 my $self = shift;
894 1         2 $self->{$name} = undef;
895 5         28 });
896             }
897              
898             #----------------------------------------------------------------
899              
900             =head2 Scalar
901              
902             Define methods in the destination class for a scalar-valued instance
903             variable called I as follows:
904              
905             scalar => 'inst_var'
906              
907             Alternatively, you may supply a hash reference as the argument to the
908             C specification as follows:
909              
910             scalar => { name => 'inst_var', default => 42 }
911              
912             In this case, the I C attribute gives the name of the
913             scalar in the destination class. The I C attribute
914             supplies an initial value for the scalar in the destination class.
915              
916             This specification defines the following methods in the destination
917             class:
918              
919             =over
920              
921             =cut
922              
923             sub define_scalar_methods {
924 5     5 0 10 my ($dest_class, $spec) = @_;
925              
926 5         7 my $name = undef;
927              
928 5 100       16 if (ref($spec) eq 'HASH') {
929 1         3 $name = $spec->{name};
930              
931 1 50       4 if (defined $spec->{default}) {
932 1         5 _add_methodist_info($dest_class,
933             default => [ $name => $spec->{default} ]);
934             }
935             } else {
936 4         7 $name = $spec;
937             }
938              
939 5         19 _add_methodist_info($dest_class, attributes => [ scalar => $name ]);
940              
941             =item I(...)
942              
943             The method named the same as the instance variable is the setter and
944             getter. If called with no arguments, returns the current value of the
945             scalar. If called with an argument, the scalar is assigned that
946             value.
947              
948             =cut
949              
950             define_method($dest_class, $name,
951             sub {
952 22     22   39 my ($self, $arg) = @_;
953 22 100       52 if (defined $arg) {
954 7         80 return $self->{$name} = $arg;
955             }
956 15         72 $self->{$name};
957 5         27 });
958              
959             =item clear_I()
960              
961             Undefine the instance variable. This method is so named to make it
962             consistent with other methods defined by this module.
963              
964             =cut
965              
966             define_method($dest_class, "clear_$name",
967             sub {
968 1     1   2 my $self = shift;
969 1         4 $self->{$name} = undef;
970 5         39 });
971              
972             =item add_to_I($val)
973              
974             Add numeric $val to the current contents of the scalar.
975              
976             =cut
977              
978             define_method($dest_class, "add_to_$name",
979             sub {
980 2     2   7 my ($self, $val) = @_;
981 2         6 $self->{$name} += $val;
982 5         26 });
983              
984             =item inc_I()
985              
986             Increment the scalar by one and return its new value.
987              
988             =cut
989              
990             define_method($dest_class, "inc_$name",
991             sub {
992 2     2   2 my $self = shift;
993 2         5 $self->{$name}++;
994 5         54 });
995              
996             =item dec_I()
997              
998             Decrement the scalar by one and return its new value.
999              
1000             =cut
1001              
1002             define_method($dest_class, "dec_$name",
1003             sub {
1004 3     3   4 my $self = shift;
1005 3         7 $self->{$name}--;
1006 5         25 });
1007              
1008             =item append_to_I($val)
1009              
1010             Append string $val to the current contents of the scalar.
1011              
1012             =back
1013              
1014             =cut
1015              
1016             define_method($dest_class, "append_to_$name",
1017             sub {
1018 1     1   2 my ($self, $val) = @_;
1019 1         4 $self->{$name} .= $val;
1020 5         27 });
1021             }
1022              
1023             #----------------------------------------------------------------
1024              
1025             =head2 Scalars
1026              
1027             Define methods in the destination class for multiple scalar-valued
1028             instance variables as follows:
1029              
1030             scalars => [ 'alpha', 'beta', 'gamma' ]
1031              
1032             This specification is a convenience for defining multiple
1033             scalar-valued instance variables. It takes a reference to a list of
1034             names and invokes the C specification for each. Hence, the
1035             above specification is entirely equivalent to this one:
1036              
1037             scalar => 'alpha',
1038             scalar => 'beta',
1039             scalar => 'gamma'
1040              
1041             Note that there is no way to define a default value for each scalar in
1042             the C construct; use multiple C specifications
1043             instead.
1044              
1045             =cut
1046              
1047             #----------------------------------------------------------------
1048              
1049             =head2 Utility
1050              
1051             Define various utility methods.
1052              
1053             =over
1054              
1055             =cut
1056              
1057             {
1058 9     9   8752 use Class::ISA;
  9         30082  
  9         4491  
1059              
1060             # Cache previous results from self_and_super_path, which takes a
1061             # fair amount of time and is called a *lot* because it's in beget().
1062             my %self_and_super;
1063              
1064             # Invoke self_and_super_path (which returns the ordered list of
1065             # names of classes that Perl would search in order to find a
1066             # method). Cache and return results.
1067             sub _self_and_super {
1068 16     16   29 my $class = shift;
1069              
1070 16         24 my $rtn = undef;
1071 16 100       52 if (exists $self_and_super{$class}) {
1072 6         13 $rtn = $self_and_super{$class};
1073             } else {
1074 10         58 my @self_and_super = Class::ISA::self_and_super_path($class);
1075 10         296 $rtn = $self_and_super{$class} = \@self_and_super;
1076             }
1077              
1078 16         53 return $rtn;
1079             }
1080             }
1081              
1082             sub define_utility_methods {
1083 12     12 0 20 my $dest_class = shift;
1084              
1085             define_method($dest_class, 'beget',
1086             sub {
1087 16     16   44 my ($dest_class, %initializers) = @_;
1088              
1089 16         45 my $self = bless { }, $dest_class;
1090 16         67 $self->equip(%initializers);
1091 12         60 });
1092              
1093             define_method($dest_class, 'equip',
1094             sub {
1095 16     16   36 my ($self, %initializers) = @_;
1096              
1097 16         29 foreach my $class (@{_self_and_super(ref $self)}) {
  16         61  
1098 22 100       61 next unless _has_methodist_info($class);
1099              
1100 15         48 foreach my $pair (_get_methodist_info($class,
1101             'attributes')) {
1102 29         62 my ($type, $name) = @$pair;
1103             SWITCH:
1104 29         94 for ($type) {
1105 29 100       155 /scalar|enum/ and do {
1106 10         33 $self->{$name} = undef;
1107 10         26 last SWITCH;
1108             };
1109 19 100       54 /list/ and do {
1110 10         28 $self->{$name} = [ ];
1111 10         23 last SWITCH;
1112             };
1113 9 50       51 /hash/ and do {
1114 9         32 $self->{$name} = { };
1115 9         25 last SWITCH;
1116             };
1117 0         0 confess "Invalid type '$type'";
1118             }
1119             }
1120              
1121 15         39 foreach my $pair (_get_methodist_info($class,
1122             'default')) {
1123 2         6 my ($name, $default) = @$pair;
1124 2         10 $self->{$name} = $default;
1125             }
1126             }
1127              
1128 16         75 while (my ($key, $value) = each %initializers) {
1129 1         3 $self->$key($value);
1130             }
1131              
1132 16         63 return $self;
1133 12         73 });
1134              
1135 9     9   13644 use Data::Dumper;
  9         106151  
  9         4588  
1136 12         20 $Data::Dumper::Indent = 1;
1137              
1138             =item toString()
1139              
1140             Define a method to convert an object to a string using
1141             C.
1142              
1143             =cut
1144              
1145             define_method($dest_class, 'toString',
1146             sub {
1147 0     0   0 my $self = shift;
1148 0         0 Data::Dumper->Dump([ $self ], [ ref $self ]);
1149 12         47 });
1150              
1151             =item attributes_as_string(@attributes)
1152              
1153             Return a string representation of the object, including attribute
1154             name-value pairs for attributes named in parameter list.
1155              
1156             =cut
1157              
1158 3     3 0 10 sub ansi_magenta { "\e[35m" }
1159 0     0 0 0 sub ansi_underline { "\e[4m" }
1160 3     3 0 12 sub ansi_reset { "\e[0m" }
1161              
1162             define_method($dest_class, 'attributes_as_string',
1163             sub {
1164 3     3   39 my ($self, @attributes) = @_;
1165 3         5 my @pairs;
1166 3         6 foreach my $attribute (@attributes) {
1167 3   50     9 my $value = $self->{$attribute} || 'UNDEF';
1168              
1169 3 100       16 if (ref($value) eq 'ARRAY') {
    50          
1170 1         5 $value = sprintf('[%s]', join(',', @$value));
1171              
1172             } elsif (ref($value) eq 'HASH') {
1173 5   50     24 my @contents =
1174 2         10 map { sprintf("%s=%s", $_, $value->{$_} || 'UNDEF') }
1175             sort keys %$value;
1176 2         9 $value = sprintf('{%s}', join(',', @contents));
1177             }
1178              
1179             # Use ANSI colorization for attribute name.
1180 3         12 push @pairs,
1181             sprintf('%s%s%s=%s',
1182             ansi_magenta, $attribute, ansi_reset, $value)
1183             }
1184 3         16 sprintf('(%s %s)', ref($self), join(',', @pairs));
1185 12         70 });
1186              
1187             =item dump([$msge])
1188              
1189             Define a method to dump an object using C. If C<$msge>
1190             is defined, print it as a brief descriptive message before dumping the
1191             object. These methods are defined on all classes that use
1192             C.
1193              
1194             =cut
1195              
1196             define_method($dest_class, 'dump',
1197             sub {
1198 0     0   0 my ($self, $msge) = @_;
1199              
1200 0 0       0 print "==== $msge ====\n" if $msge;
1201 0         0 print $self->toString();
1202 12         64 });
1203             }
1204              
1205             'SDG'; # Return true
1206              
1207             __END__