File Coverage

blib/lib/Class/MakeMethods/Emulator/MethodMaker.pm
Criterion Covered Total %
statement 52 66 78.7
branch 42 64 65.6
condition 15 30 50.0
subroutine 31 37 83.7
pod 27 32 84.3
total 167 229 72.9


line stmt bran cond sub pod time code
1             package Class::MakeMethods::Emulator::MethodMaker;
2              
3 35     35   100179 use Class::MakeMethods '-isasubclass';
  35         110  
  35         358  
4             require Class::MakeMethods::Emulator;
5              
6             $VERSION = 1.03;
7              
8 35     35   201 use strict;
  35         65  
  35         70054  
9              
10             =head1 NAME
11              
12             Class::MakeMethods::Emulator::MethodMaker - Emulate Class::MethodMaker
13              
14              
15             =head1 SYNOPSIS
16              
17             package MyObject;
18             use Class::MakeMethods::Emulator::MethodMaker(
19             new_with_init => 'new',
20             get_set => [ qw / foo bar baz / ];
21             );
22              
23             ... OR ...
24              
25             package MyObject;
26             use Class::MakeMethods::Emulator::MethodMaker '-take_namespace';
27             use Class::MethodMaker (
28             new_with_init => 'new',
29             get_set => [ qw / foo bar baz / ];
30             );
31              
32              
33             =head1 DESCRIPTION
34              
35             This module provides emulation of Class::MethodMaker, using the Class::MakeMethods framework.
36              
37             Although originally based on Class::MethodMaker, the calling convention
38             for Class::MakeMethods differs in a variety of ways; most notably, the names
39             given to various types of methods have been changed, and the format for
40             specifying method attributes has been standardized. This package uses
41             the aliasing capability provided by Class::MakeMethods, defining methods
42             that modify the declaration arguments as necessary and pass them off to
43             various subclasses of Class::MakeMethods.
44              
45              
46             =head1 COMPATIBILITY
47              
48             Full compatibility is maintained with version 1.03; some of the
49             changes in versions 1.04 through 1.10 are not yet included.
50              
51             The test suite from Class::MethodMaker version 1.10 is included
52             with this package, in the t/emulator_class_methodmaker/ directory.
53             The unsupported tests have names ending in ".todo".
54              
55             The tests are unchanged from those in the Class::MethodMaker
56             distribution, except for the substitution of
57             C in the place of
58             C.
59              
60             In cases where earlier distributions of Class::MethodMaker contained
61             a different version of a test, it is also included. (Note that
62             version 0.92's get_concat returned '' for empty values, but in
63             version 0.96 this was changed to undef; this emulator follows the
64             later behavior. To avoid "use of undefined value" warnings from
65             the 0.92 version of get_concat.t, that test has been modified by
66             appending a new flag after the name, C<'get_concat --noundef'>,
67             which restores the earlier behavior.)
68              
69              
70             =head1 USAGE
71              
72             There are several ways to call this emulation module:
73              
74             =over 4
75              
76             =item *
77              
78             Direct Access
79              
80             Replace occurances in your code of C with C.
81              
82             =item *
83              
84             Install Emulation
85              
86             If you C, the Class::MethodMaker namespace will be aliased to this package, and calls to the original package will be transparently handled by this emulator.
87              
88             To remove the emulation aliasing, call C.
89              
90             B This affects B subsequent uses of Class::MethodMaker in your program, including those in other modules, and might cause unexpected effects.
91              
92             =item *
93              
94             The -sugar Option
95              
96             Passing '-sugar' as the first argument in a use or import call will cause the 'methods' package to be declared as an alias to this one.
97              
98             This allows you to write declarations in the following manner.
99              
100             use Class::MakeMethods::Emulator::MethodMaker '-sugar';
101              
102             make methods
103             get_set => [ qw / foo bar baz / ],
104             list => [ qw / a b c / ];
105              
106             B This feature is deprecated in Class::MethodMaker version 0.96 and later.
107              
108             =back
109              
110             =cut
111              
112             my $emulation_target = 'Class::MethodMaker';
113              
114             sub import {
115 36     36   613 my $mm_class = shift;
116            
117 36 50 33     1248 if ( scalar @_ and $_[0] =~ /^-take_namespace/ and shift ) {
    50 33        
      33        
      33        
118 0         0 Class::MakeMethods::Emulator::namespace_capture(__PACKAGE__, $emulation_target);
119             } elsif ( scalar @_ and $_[0] =~ /^-release_namespace/ and shift ) {
120 0         0 Class::MakeMethods::Emulator::namespace_release(__PACKAGE__, $emulation_target);
121             }
122            
123 36 100 66     334 if ( scalar @_ and $_[0] eq '-sugar' and shift ) {
      66        
124 1         4 Class::MakeMethods::Emulator::namespace_capture(__PACKAGE__, "methods");
125             }
126            
127 36 100       1408 $mm_class->make( @_ ) if ( scalar @_ );
128             }
129              
130              
131             =head1 METHOD CATALOG
132              
133             B The documentation below is derived from version 1.02 of
134             Class::MethodMaker. Class::MakeMethods::Emulator::MethodMaker
135             provides support for all of the features and examples shown below,
136             with no changes required.
137              
138              
139             =head1 CONSTRUCTOR METHODS
140              
141             =head2 new
142              
143             Equivalent to Class::MakeMethods 'Template::Hash:new --with_values'.
144              
145             =cut
146              
147 4     4 1 13 sub new { return 'Template::Hash:new --with_values' }
148              
149              
150             =head2 new_with_init
151              
152             Equivalent to Class::MakeMethods 'Template::Hash:new --with_init'.
153              
154             =cut
155              
156 3     3 1 10 sub new_with_init { return 'Template::Hash:new --with_init' }
157              
158              
159             =head2 new_hash_init
160              
161             Equivalent to Class::MakeMethods 'Template::Hash:new --instance_with_methods'.
162              
163             =cut
164              
165 3     3 1 11 sub new_hash_init { return 'Template::Hash:new --instance_with_methods' }
166              
167              
168             =head2 new_with_args
169              
170             Equivalent to Class::MakeMethods 'Template::Hash:new --with_values'.
171              
172             =cut
173              
174 1     1 1 4 sub new_with_args { return 'Template::Hash:new --with_values' }
175              
176              
177             =head2 copy
178              
179             Equivalent to Class::MakeMethods 'Template::Hash:new --copy_with_values'.
180              
181             =cut
182              
183 1     1 1 5 sub copy { return 'Template::Hash:new --copy_with_values' }
184              
185              
186             =head1 SCALAR ACCESSORS
187              
188             =head2 get_set
189              
190             Basically equivalent to Class::MakeMethods 'Template::Hash:scalar', except that various arguments are intercepted and converted into the parallel Class::MakeMethods::Template interface declarations.
191              
192             =cut
193              
194             my $scalar_interface = { '*'=>'get_set', 'clear_*'=>'clear' };
195              
196             sub get_set {
197             shift and return [
198 26 50       216 ( ( $_[0] and $_[0] eq '-static' and shift ) ? 'Template::Static:scalar'
    50          
    50          
    50          
    100          
    100          
    100          
    100          
199             : 'Template::Hash:scalar' ),
200             '-interface' => $scalar_interface,
201             map {
202 10 100 66 10 1 4644 ( ref($_) eq 'ARRAY' )
    50          
203             ? ( '-interface'=>{
204             ( $_->[0] ? ( $_->[0] => 'get_set' ) : () ),
205             ( $_->[1] ? ( $_->[1] => 'clear' ) : () ),
206             ( $_->[2] ? ( $_->[2] => 'get' ) : () ),
207             ( $_->[3] ? ( $_->[3] => 'set_return' ) : () ),
208             } )
209             : ($_ eq '-compatibility')
210             ? ( '-interface', $scalar_interface )
211             : ($_ eq '-noclear')
212             ? ( '-interface', 'default' )
213             : ( /^-/ ? "-$_" : $_ )
214             } @_
215             ]
216             }
217              
218              
219             =head2 get_concat
220              
221             Equivalent to Class::MakeMethods 'Template::Hash:string' with a special interface declaration that provides the get_concat and clear behaviors.
222              
223             =cut
224              
225             my $get_concat_interface = {
226             '*'=>'get_concat', 'clear_*'=>'clear',
227             '-params'=>{ 'join' => '', 'return_value_undefined' => undef() }
228             };
229              
230             my $old_get_concat_interface = {
231             '*'=>'get_concat', 'clear_*'=>'clear',
232             '-params'=>{ 'join' => '', 'return_value_undefined' => '' }
233             };
234              
235             sub get_concat {
236 3 100 33 3 1 29 shift and return [ 'Template::Hash:string', '-interface',
    50          
237             ( $_[0] eq '--noundef' ? ( shift and $old_get_concat_interface )
238             : $get_concat_interface ), @_ ]
239             }
240              
241             =head2 counter
242              
243             Equivalent to Class::MakeMethods 'Template::Hash:number --counter'.
244              
245             =cut
246              
247 1     1 1 3 sub counter { return 'Template::Hash:number --counter' }
248              
249              
250             =head1 OBJECT ACCESSORS
251              
252             Basically equivalent to Class::MakeMethods 'Template::Hash:object' with an declaration that provides the "delete_x" interface. Due to a difference in expected argument syntax, the incoming arguments are revised before being delegated to Template::Hash:object.
253              
254             =cut
255              
256             my $object_interface = { '*'=>'get_set_init', 'delete_*'=>'clear' };
257              
258             sub object {
259             shift and return [
260 2 50   2 0 8 'Template::Hash:object',
261             '-interface' => $object_interface,
262             _object_args(@_)
263             ]
264             }
265              
266             sub _object_args {
267 4     4   8 my @meta_methods;
268 4 50       33 ! (@_ % 2) or Carp::croak("Odd number of arguments for object declaration");
269 4         15 while ( scalar @_ ) {
270 9         16 my ($class, $list) = (shift(), shift());
271 14 100 66     135 push @meta_methods, map {
272 9 100       25 (! ref $_) ? { name=> $_, class=>$class }
273             : { name=> $_->{'slot'}, class=>$class,
274             delegate=>( $_->{'forward'} || $_->{'comp_mthds'} ) }
275             } ( ( ref($list) eq 'ARRAY' ) ? @$list : ($list) );
276             }
277 4         24 return @meta_methods;
278             }
279              
280              
281             =head2 object_list
282              
283             Basically equivalent to Class::MakeMethods 'Template::Hash:object_list' with an declaration that provides the relevant helper methods. Due to a difference in expected argument syntax, the incoming arguments are revised before being delegated to Template::Hash:object_list.
284              
285             =cut
286              
287             my $array_interface = {
288             '*'=>'get_push',
289             '*_set'=>'set_items', 'set_*'=>'set_items',
290             map( ('*_'.$_ => $_, $_.'_*' => $_ ),
291             qw( pop push unshift shift splice clear count ref index )),
292             };
293              
294             sub object_list {
295             shift and return [
296 2 50   2 1 13 'Template::Hash:array_of_objects',
297             '-interface' => $array_interface,
298             _object_args(@_)
299             ];
300             }
301              
302             =head2 forward
303              
304             Basically equivalent to Class::MakeMethods 'Template::Universal:forward_methods'. Due to a difference in expected argument syntax, the incoming arguments are revised before being delegated to Template::Universal:forward_methods.
305              
306             forward => [ comp => 'method1', comp2 => 'method2' ]
307              
308             Define pass-through methods for certain fields. The above defines that
309             method C will be handled by component C, whilst method
310             C will be handled by component C.
311              
312             =cut
313              
314             sub forward {
315 0     0 1 0 my $class = shift;
316 0         0 my @results;
317 0         0 while ( scalar @_ ) {
318 0         0 my ($comp, $method) = ( shift, shift );
319 0         0 push @results, { name=> $method, target=> $comp };
320             }
321 0         0 [ 'forward_methods', @results ]
322             }
323              
324              
325              
326             =head1 REFERENCE ACCESSORS
327              
328             =head2 list
329              
330             Equivalent to Class::MakeMethods 'Template::Hash:array' with a custom method naming interface.
331              
332             =cut
333              
334             sub list {
335 6 50   6 1 46 shift and return [ 'Template::Hash:array', '-interface' => $array_interface, @_ ];
336             }
337              
338              
339             =head2 hash
340              
341             Equivalent to Class::MakeMethods 'Template::Hash:hash' with a custom method naming interface.
342              
343             =cut
344              
345             my $hash_interface = {
346             '*'=>'get_push',
347             '*s'=>'get_push',
348             'add_*'=>'get_set_items',
349             'add_*s'=>'get_set_items',
350             'clear_*'=>'delete',
351             'clear_*s'=>'delete',
352             map {'*_'.$_ => $_} qw(push set keys values exists delete tally clear),
353             };
354              
355             sub hash {
356 4 50   4 1 26 shift and return [ 'Template::Hash:hash', '-interface' => $hash_interface, @_ ];
357             }
358              
359              
360             =head2 tie_hash
361              
362             Equivalent to Class::MakeMethods 'Template::Hash:tiedhash' with a custom method naming interface.
363              
364             =cut
365              
366             sub tie_hash {
367 1 50   1 1 8 shift and return [ 'Template::Hash:tiedhash', '-interface' => $hash_interface, @_ ];
368             }
369              
370             =head2 hash_of_lists
371              
372             Equivalent to Class::MakeMethods 'Template::Hash:hash_of_arrays', or if the -static flag is present, to 'Template::Static:hash_of_arrays'.
373              
374             =cut
375              
376             sub hash_of_lists {
377 3 100 66 3 1 39 shift and return ( $_[0] and $_[0] eq '-static' and shift )
    50          
378             ? [ 'Template::Static:hash_of_arrays', @_ ]
379             : [ 'Template::Hash:hash_of_arrays', @_ ]
380             }
381              
382              
383             =head1 STATIC ACCESSORS
384              
385             =head2 static_get_set
386              
387             Equivalent to Class::MakeMethods 'Template::Static:scalar' with a custom method naming interface.
388              
389             =cut
390              
391             sub static_get_set {
392 1 50   1 1 10 shift and return [ 'Template::Static:scalar', '-interface', $scalar_interface, @_ ]
393             }
394              
395             =head2 static_list
396              
397             Equivalent to Class::MakeMethods 'Template::Static:array' with a custom method naming interface.
398              
399             =cut
400              
401             sub static_list {
402 2 50   2 1 13 shift and return [ 'Template::Static:array', '-interface' => $array_interface, @_ ];
403             }
404              
405             =head2 static_hash
406              
407             Equivalent to Class::MakeMethods 'Template::Static:hash' with a custom method naming interface.
408              
409             =cut
410              
411             sub static_hash {
412 4 50   4 1 25 shift and return [ 'Template::Static:hash', '-interface' => $hash_interface, @_ ];
413             }
414              
415              
416             =head1 GROUPED ACCESSORS
417              
418             =head2 boolean
419              
420             Equivalent to Class::MakeMethods 'Template::Static:bits' with a custom method naming interface.
421              
422             =cut
423              
424             my $bits_interface = {
425             '*'=>'get_set', 'set_*'=>'set_true', 'clear_*'=>'set_false',
426             'bit_fields'=>'bit_names', 'bits'=>'bit_string', 'bit_dump'=>'bit_hash'
427             };
428              
429             sub boolean {
430 5 50   5 1 30 shift and return [ 'Template::Hash:bits', '-interface' => $bits_interface, @_ ];
431             }
432              
433              
434             =head2 grouped_fields
435              
436             Creates get/set methods like get_set but also defines a method which
437             returns a list of the slots in the group.
438              
439             use Class::MakeMethods::Emulator::MethodMaker
440             grouped_fields => [
441             some_group => [ qw / field1 field2 field3 / ],
442             ];
443              
444             Its argument list is parsed as a hash of group-name => field-list
445             pairs. Get-set methods are defined for all the fields and a method with
446             the name of the group is defined which returns the list of fields in the
447             group.
448              
449             =cut
450              
451             sub grouped_fields {
452 1     1 1 8 my ($class, %args) = @_;
453 1         1 my @methods;
454 1         5 foreach (keys %args) {
455 1         2 my @slots = @{ $args{$_} };
  1         4  
456             push @methods,
457 1     1   13 $_, sub { @slots },
458 1         19 $class->make( 'get_set', \@slots );
459             }
460 1         7 return @methods;
461             }
462              
463             =head2 struct
464              
465             Equivalent to Class::MakeMethods 'Template::Hash::struct'.
466              
467             B This feature is included but not documented in Class::MethodMaker version 1.
468              
469              
470             =cut
471              
472 2     2 1 6 sub struct { return 'Template::Hash:struct' }
473              
474              
475             =head1 INDEXED ACCESSORS
476              
477             =head2 listed_attrib
478              
479             Equivalent to Class::MakeMethods 'Template::Flyweight:boolean_index' with a custom method naming interface.
480              
481             =cut
482              
483             sub listed_attrib {
484 2 50   2 1 17 shift and return [ 'Template::Flyweight:boolean_index', '-interface' => {
485             '*'=>'get_set', 'set_*'=>'set_true', 'clear_*'=>'set_false',
486             '*_objects'=>'find_true', }, @_ ]
487             }
488              
489              
490             =head2 key_attrib
491              
492             Equivalent to Class::MakeMethods 'Template::Hash:string_index'.
493              
494             =cut
495              
496 2     2 1 7 sub key_attrib { return 'Template::Hash:string_index' }
497              
498             =head2 key_with_create
499              
500             Equivalent to Class::MakeMethods 'Template::Hash:string_index --find_or_new'.
501              
502             =cut
503              
504 2     2 1 8 sub key_with_create { return 'Template::Hash:string_index --find_or_new'}
505              
506              
507             =head1 CODE ACCESSORS
508              
509             =head2 code
510              
511             Equivalent to Class::MakeMethods 'Template::Hash:code'.
512              
513             =cut
514              
515 2     2 1 6 sub code { return 'Template::Hash:code' }
516              
517              
518             =head2 method
519              
520             Equivalent to Class::MakeMethods 'Template::Hash:code --method'.
521              
522             =cut
523              
524 2     2 1 8 sub method { return 'Template::Hash:code --method' }
525              
526              
527             =head2 abstract
528              
529             Equivalent to Class::MakeMethods 'Template::Universal:croak --abstract'.
530              
531             =cut
532              
533 3     3 1 10 sub abstract { return 'Template::Universal:croak --abstract' }
534              
535              
536             =head1 ARRAY CONSTRUCTOR AND ACCESSORS
537              
538             =head2 builtin_class (EXPERIMENTAL)
539              
540             Equivalent to Class::MakeMethods 'Template::StructBuiltin:builtin_isa' with a modified argument order.
541              
542             =cut
543              
544             sub builtin_class {
545 0           shift and return [ 'Template::StructBuiltin:builtin_isa',
546 0 0   0 1   '-new_function'=>(shift), @{(shift)} ]
547             }
548              
549             =head1 CONVERSION
550              
551             If you wish to convert your code from use of the Class::MethodMaker emulator to direct use of Class::MakeMethods, you will need to adjust the arguments specified in your C or C calls.
552              
553             Often this is simply a matter of replacing the names of aliased method-types listed below with the new equivalents.
554              
555             For example, suppose that you code contained the following declaration:
556              
557             use Class::MethodMaker (
558             counter => [ 'foo' ]
559             );
560              
561             Consulting the listings below you can find that C is an alias for C and you could thus revise your declaration to read:
562              
563             use Class::MakeMethods (
564             'Hash:number --counter' => [ 'foo' ]
565             );
566              
567             However, note that those methods marked "(with custom interface)" below have a different default naming convention for helper methods in Class::MakeMethods, and you will need to either supply a similar interface or alter your module's calling interface.
568              
569             Also note that the C, C, and C method types, marked "(with modified arguments)" below, require their arguments to be specified differently.
570              
571             See L for more information about the default interfaces of these method types.
572              
573              
574             =head2 Hash methods
575              
576             The following equivalencies are declared for old meta-method names that are now handled by the Hash implementation:
577              
578             new 'Template::Hash:new --with_values'
579             new_with_init 'Template::Hash:new --with_init'
580             new_hash_init 'Template::Hash:new --instance_with_methods'
581             copy 'Template::Hash:copy'
582             get_set 'Template::Hash:scalar' (with custom interfaces)
583             counter 'Template::Hash:number --counter'
584             get_concat 'Template::Hash:string --get_concat' (with custom interface)
585             boolean 'Template::Hash:bits' (with custom interface)
586             list 'Template::Hash:array' (with custom interface)
587             struct 'Template::Hash:struct'
588             hash 'Template::Hash:hash' (with custom interface)
589             tie_hash 'Template::Hash:tiedhash' (with custom interface)
590             hash_of_lists 'Template::Hash:hash_of_arrays'
591             code 'Template::Hash:code'
592             method 'Template::Hash:code --method'
593             object 'Template::Hash:object' (with custom interface and modified arguments)
594             object_list 'Template::Hash:array_of_objects' (with custom interface and modified arguments)
595             key_attrib 'Template::Hash:string_index'
596             key_with_create 'Template::Hash:string_index --find_or_new'
597              
598             =head2 Static methods
599              
600             The following equivalencies are declared for old meta-method names
601             that are now handled by the Static implementation:
602              
603             static_get_set 'Template::Static:scalar' (with custom interface)
604             static_hash 'Template::Static:hash' (with custom interface)
605              
606             =head2 Flyweight method
607              
608             The following equivalency is declared for the one old meta-method name
609             that us now handled by the Flyweight implementation:
610              
611             listed_attrib 'Template::Flyweight:boolean_index'
612              
613             =head2 Struct methods
614              
615             The following equivalencies are declared for old meta-method names
616             that are now handled by the Struct implementation:
617              
618             builtin_class 'Template::Struct:builtin_isa'
619              
620             =head2 Universal methods
621              
622             The following equivalencies are declared for old meta-method names
623             that are now handled by the Universal implementation:
624              
625             abstract 'Template::Universal:croak --abstract'
626             forward 'Template::Universal:forward_methods' (with modified arguments)
627              
628              
629             =head1 EXTENDING
630              
631             In order to enable third-party subclasses of MethodMaker to run under this emulator, several aliases or stub replacements are provided for internal Class::MethodMaker methods which have been eliminated or renamed.
632              
633             =over 4
634              
635             =item *
636              
637             install_methods - now simply return the desired methods
638              
639             =item *
640              
641             find_target_class - now passed in as the target_class attribute
642              
643             =item *
644              
645             ima_method_maker - no longer supported; use target_class instead
646              
647             =back
648              
649             =cut
650              
651 0     0 0   sub find_target_class { (shift)->_context('TargetClass') }
652 0     0 0   sub get_target_class { (shift)->_context('TargetClass') }
653 0     0 0   sub install_methods { (shift)->_install_methods(@_) }
654 0     0 0   sub ima_method_maker { 1 }
655              
656              
657             =head1 BUGS
658              
659             This module aims to provide a 100% compatible drop-in replacement for Class::MethodMaker; if you detect a difference when using this emulation, please inform the author.
660              
661              
662             =head1 SEE ALSO
663              
664             See L for general information about this distribution.
665              
666             See L for more about this family of subclasses.
667              
668             See L for more information about the original module.
669              
670             A good introduction to Class::MethodMaker is provided by pages 222-234 of I, by Damian Conway (Manning, 1999).
671              
672             http://www.browsebooks.com/Conway/
673              
674             =cut
675              
676             1;