File Coverage

blib/lib/Attribute/GlobalEnable.pm
Criterion Covered Total %
statement 168 178 94.3
branch 56 84 66.6
condition 11 20 55.0
subroutine 28 29 96.5
pod 0 4 0.0
total 263 315 83.4


line stmt bran cond sub pod time code
1             package Attribute::GlobalEnable;
2              
3             our $VERSION = '0.1';
4              
5 12     12   374817 use strict;
  12         32  
  12         557  
6 12     12   61 use warnings;
  12         21  
  12         278  
7 12     12   12079 use Attribute::Handlers;
  12         99093  
  12         90  
8 12     12   806 use Carp qw( croak );
  12         28  
  12         889  
9 12     12   69 use base qw( Exporter );
  12         23  
  12         1459  
10 12     12   14630 use Time::HiRes qw( time );
  12         26301  
  12         64  
11              
12              
13             ## hold the switch settings for each module, method etc. (see above)
14             my $ENABLE_CHK = {};
15              
16             ## set the hash for the Debug attribute and the key for the hash ##
17             my $ENABLE_ATTR = {};
18              
19             ## hold flag definitions.
20             my $ENABLE_FLAG = {};
21              
22             ## hold our current package (our sub-package name really)
23             my $PACKAGE = '';
24              
25             ## mark this as true once we've automatically loaded all the stuff. It's
26             ## once true, other packages that load this module will ONLY get the
27             ## symbols exported.
28             my $DONE_INIT = 0;
29              
30              
31              
32             ##
33             ## import is an auto sub... happens when you... well... import. In our case
34             ## it automatically exports our attribute functionality to the properr places.
35             ## The first time it runs should be when it is initialized. After this
36             ## initialization process, it will only export the proper symbols (checks
37             ## $DONE_INIT).
38             ##
39             ## this should return true if it is successfull... it should bail otherwise.
40             sub import {
41 12 50   12   224 return _export_my_attribute_symbols() if $DONE_INIT;
42 12         24 my $class = shift();
43 12 50       45 croak "Must specify some arguments." if not @_;
44 12         47 my $args = {@_};
45              
46             ## set the package to the caller
47 12         44 $PACKAGE = caller();
48 12 50 33     117 croak "Must sub-package ".$PACKAGE if not $PACKAGE or $PACKAGE eq __PACKAGE__;
49              
50             ## make sure our sub-packaged module is using the exporter
51 12 50       187 _export_the_exporter_to( $PACKAGE ) or die "Bad exporting exporter";
52              
53             ## check to make sure ENABLE_CHK exists, and is a hashref ##
54 12 50 33     116 if ( not $args->{ENABLE_CHK} or ref $args->{ENABLE_CHK} ne 'HASH' ) {
55 0         0 croak "ENABLE_CHK needs to be set with a hash ref for this module "
56             ."to be used.";
57             }
58              
59             ## build the enabled attributes and store internally
60 12 50       41 _check_and_build_enable_attr($args) or die "bad ENABLE_ATTR";
61              
62             ## handle the flags array and store internally.
63 12 50       37 _check_and_build_enable_flags($args) or die "Bad ENABLE_FLAGS";
64              
65             ## convert the checks from the passed in hash to our internal hash ##
66 12 50       45 _build_enable_chks($args) or die "Bad ENABLE_CHK";
67              
68             ## build and export the attribute functions
69 12 50       42 _build_attr_exports() or die "Bad build ATTR exports";
70              
71             ## export the proper subs to the package that init'd this ##
72 12         238 _export_my_attribute_symbols();
73              
74 12         492 return $DONE_INIT++;
75             }
76              
77              
78              
79              
80              
81             sub _export_the_exporter_to {
82 12     12   25 my $package = shift();
83              
84 12         43 my $eval_str = "{ package $package; use Exporter; use base qw( Exporter ); }";
85 12     12   75 eval $eval_str;
  12     12   25  
  12         825  
  12         59  
  12         22  
  12         1407  
  12         947  
86 12 50       49 _eval_die($eval_str, $@) if $@;
87              
88 12         49 return 1;
89             }
90              
91              
92              
93              
94             sub _build_attr_exports {
95             ## set the proper attribute functions to point to our internal handler ##
96 12     12   39 foreach my $attribute ( keys %$ENABLE_ATTR ) {
97              
98             ## set the attribute function to our internal one ##
99 24         88 my $eval_str = "sub UNIVERSAL::$attribute : ATTR(CODE) { return "
100             . __PACKAGE__ ."::My_attr_handler(\@_) }";
101              
102 12     12 0 86 eval $eval_str;
  12     12 0 21  
  12     11   97  
  12     12   27039  
  12         68  
  12         25  
  12         53  
  11         10964  
  24         2444  
103 24 50       8604 _eval_die( $eval_str, $@) if $@;
104              
105             ## set exporting for each attribute as well so that we can get imported
106             ## $attributes as function calls.
107 24         93 $eval_str = "push \@${PACKAGE}::EXPORT_OK, \$attribute; "
108             ."push \@${PACKAGE}::EXPORT, \$attribute;";
109              
110 24         1993 eval $eval_str;
111 24 50       107 _eval_die( $eval_str, $@) if $@;
112              
113             ## set our internal ref to our wrapper for function calls only if
114             ## there are some switches turned on in ENABLE_CHK.
115 24         153 $eval_str = "sub ". $PACKAGE ."::$attribute ";
116 24 100 100     35 if ( %{$ENABLE_CHK->{$attribute}} || %{$ENABLE_FLAG->{$attribute}}) {
  24         134  
  15         146  
117 14         181 $eval_str .= "{ return " . __PACKAGE__
118             ."::my_static_handler('$attribute', \@_) }";
119             } else {
120             ## do nothing.
121 10         21 $eval_str .= "{ }";
122             }
123              
124 24     11   1360 eval $eval_str;
  11     24   8484  
  24         1658  
125 24 50       104 _eval_die( $eval_str, $@) if $@;
126             }
127              
128 12         62 return 1;
129             }
130              
131              
132              
133              
134             sub _build_enable_chks {
135 12     12   23 my $args = shift();
136 12         39 OUTER: foreach my $attr_str ( keys %$ENABLE_ATTR ) {
137 24         47 my $key_str = $ENABLE_ATTR->{$attr_str};
138 24         31 INNER: foreach my $db_var ( keys %{$args->{ENABLE_CHK}} ) {
  24         232  
139 370 100       3615 if ( $db_var =~ m/^(\w+?)?_?${key_str}_?(\w+)?$/ ) {
140 12         28 my $our_key = $db_var;
141 12         35 my $one = $1;
142 12 50 66     72 $our_key = "ALL_$key_str", $one = 'ALL' if not $1 and not $2;
143             ## substitute any __ with the normal :: perly syntax. ##
144 12         33 $our_key =~ s/__/::/g;
145              
146             ##
147             ## there are 2 pre-tags available: NO and ALL. NO trumps everything.
148             ## emptying the hash for that attribute. ALL empties it, but just sets
149             ## itself.
150 12 100       38 if ($one) {
151 6 50       84 if( $args->{ENABLE_CHK}->{$db_var}) {
152 6         20 $ENABLE_CHK->{$attr_str} = {};
153 6 100       37 if ( $one eq 'NO' ) {
    50          
154 1         6 next OUTER;
155             } elsif ( $one eq 'ALL' ) {
156 5         19 $ENABLE_CHK->{$attr_str}->{$our_key}
157             = $args->{ENABLE_CHK}->{$db_var};
158 5         24 next OUTER;
159             }
160 0         0 my $eval_str = "push \@${PACKAGE}::EXPORT_OK, \$attribute; "
161             ."push \@${PACKAGE}::EXPORT, \$attribute;";
162 0         0 eval $eval_str;
163 0 0       0 _eval_die( $eval_str, $@) if $@;
164             }
165             }
166              
167              
168             ## only store those values that are true. We want ENABLE_CHK to
169             ## be empty if there are no debugging flags set so our Debug
170             ## calls optomize to doing nothing at all.
171 6 50       108 $ENABLE_CHK->{$attr_str}->{ $our_key } = $args->{ENABLE_CHK}->{$db_var}
172             if $args->{ENABLE_CHK}->{$db_var};
173             }
174             }
175             }
176 12         54 return 1;
177             }
178              
179              
180              
181              
182             sub _check_and_build_enable_attr {
183 12     12   22 my $args = shift();
184              
185 12 50 33     110 if ( not $args->{ENABLE_ATTR} or ref $args->{ENABLE_ATTR} ne 'HASH' ) {
186 0         0 croak "ENABLE_ATTR must be set with a ref to a hash containing "
187             ."attribute names => key name.";
188             } else {
189 12         28 foreach my $key ( keys %{ $args->{ENABLE_ATTR} } ) {
  12         69  
190 24 50 33     280 croak "$key or". $args->{ENABLE_ATTR}->{$key} ."must be in valid format."
191             if $key !~ m/^\w+$/ or $args->{ENABLE_ATTR}->{$key} !~ m/^\w+$/;
192              
193 24         67 $ENABLE_ATTR->{$key} = $args->{ENABLE_ATTR}->{$key};
194 24         48 $ENABLE_CHK->{ $key} = {};
195 24         64 $ENABLE_FLAG->{$key} = {};
196             }
197             }
198 12         49 return 1;
199             }
200              
201              
202              
203             sub _check_and_build_enable_flags {
204 12     12   25 my $args = shift();
205              
206             ## set the FLAGS (if there are any) ##
207 12         18 foreach my $attr ( keys %{ $args->{ENABLE_FLAG} } ) {
  12         45  
208 12 50       49 if ( ref $args->{ENABLE_FLAG}->{$attr} eq 'ARRAY' ) {
209 12         20 foreach my $flag ( @{$args->{ENABLE_FLAG}->{$attr}} ) {
  12         30  
210 12         34 $ENABLE_FLAG->{$attr}->{$flag} = 1;
211             ## we want to export this as a constant too, so lets do that here ##
212 12         45 my $eval_str = "{ package $PACKAGE; use constant $flag => '$flag'; }";
213 12     12   73 eval $eval_str;
  12         273  
  12         952  
  12         973  
214 12 50       50 _eval_die( $eval_str, $@) if $@;
215              
216 12         108 $eval_str = "push \@${PACKAGE}::EXPORT_OK, '$flag'; "
217             ."push \@${PACKAGE}::EXPORT, '$flag';";
218 12         1034 eval $eval_str;
219 12 50       88 _eval_die( $eval_str, $@) if $@;
220             }
221             } else {
222 0         0 croak "ENABLE_FLAG needs to be set with an array";
223             }
224             }
225              
226 12         52 return 1;
227             }
228              
229             sub _export_my_attribute_symbols {
230             ## export this functionality to the package that called it ##
231 12     12   42 foreach my $attribute ( keys %$ENABLE_ATTR ) {
232 24         2746 $PACKAGE->export_to_level(2, $PACKAGE, $attribute);
233              
234             ## auto export flags for each one too ##
235 24         41 foreach my $flag ( keys %{ $ENABLE_FLAG->{$attribute}} ) {
  24         99  
236 12         715 $PACKAGE->export_to_level(2, $PACKAGE, $flag);
237             }
238             }
239             }
240              
241              
242             sub _eval_die {
243 0     0   0 my $eval_str = shift();
244 0         0 my $dol_at = shift();
245              
246 0         0 die "Our eval failed: $@ : $eval_str";
247             }
248              
249             ##
250             ## Attributes _should_ be mixed case or the Attribute handler will bitch
251             ## NOTE: Using UNIVERSAL should install this so everything can use it.
252             ##
253             ## Debug will replace all subroutines that have the Debug attribute
254             ## with a wrapper sub that will handle printing debugging information for
255             ## each particular function call. The beauty of this method is that this
256             ## is only enabled at compile time, so there _should_ be no (or little) overhead
257             ## at run time.
258             ##
259             ## also, the sub will only be redefined if the PERL_ENABLE environment variable
260             ## was set to true.
261             #sub UNIVERSAL::Debug :ATTR {
262             sub My_attr_handler {
263 23     23 0 55 my $attribute = $_[3];
264              
265             ## only do this if debugging is on in your environment ##
266 23 100       34 return if not %{$ENABLE_CHK->{$attribute}};
  23         185  
267              
268             ## see perldoc Attribute::Handlers for full list of what @_ is here.
269 10 50       46 my $symbol = $_[1] or die "No symbol?";
270              
271             ## convert the symbol to a scalar and get rid of any crap in the begining ##
272 10         27 my $chk = scalar( *$symbol );
273 10         93 $chk =~ s/^\*//;
274              
275             ## return if the debug level wasn't set NOTE: $_[0] is the package name
276             ## see perldoc Attribute::Handlers for what @_ is.
277 10 100       44 my $debug_level = _is_attribute_on( $attribute, $_[0], $chk) or return;
278              
279             ## this is how to set some debugging stuff. You're method call is now
280             ## wrapped at compile time. You've got to shut up warnings, or it will
281             ## bitch about this being redefined. (hence the 'no warnings')
282 12     12   27632 no warnings;
  12         31  
  12         20403  
283 7         31 return *$symbol = _generate_attr_sub(@_, $debug_level);
284             }
285              
286              
287             sub _is_attribute_on {
288 34     34   65 my $attribute = shift();
289 34         52 my $package = shift();
290 34         72 my $chk = shift();
291 34         79 my $debug_str = $ENABLE_ATTR->{$attribute};
292              
293             ## if ALL debugging is on or if package specific debugging is on
294             ## or if function specific debugging is on.
295 34         54 my $debug_level = 0;
296 34 100       233 if ( $ENABLE_CHK->{$attribute}->{"ALL_$debug_str"} ) {
    100          
    100          
297 13         39 $debug_level = $ENABLE_CHK->{$attribute}->{"ALL_$debug_str"};
298             } elsif ( $ENABLE_CHK->{$attribute}->{"${debug_str}_$chk"} ) {
299 3         11 $debug_level = $ENABLE_CHK->{$attribute}->{"${debug_str}_$chk"};
300             } elsif ( $ENABLE_CHK->{$attribute}->{"${debug_str}_$package"} ) {
301 3         11 $debug_level = $ENABLE_CHK->{$attribute}->{"${debug_str}_$package"};
302             }
303              
304 34         105 return $debug_level;
305             }
306              
307              
308             ##
309             ## this is a basic method for generating the wrapped debug sub.
310             ## it's looking for the debug_$debug_level subroutine. It'll crap out
311             ## if it can't find it. It starts looking for whatever level it's set at,
312             ## and walks down one by one till it finds an applicable debug sub.
313             sub _generate_attr_sub {
314 7     7   15 my $debug_level = pop @_;
315 7         15 my $attribute = $_[3];
316              
317 7         26 while ( $debug_level ) {
318 17         60 my $debug_sub = join( "_", "attr${attribute}", $debug_level--);
319 17 100       223 return $PACKAGE->$debug_sub( @_ ) if $PACKAGE->can( $debug_sub );
320             }
321              
322             ## crap out if we reach here cause there's no debug level for this ##
323 0         0 die "I couldn't find a debug level at or below the one set.";
324             }
325              
326              
327             ##
328             ## this handles the static function calls that are exported to each package
329             ## that wishes to use them. It checks to see if the proper flags are set
330             ## for it do run the user built function. if not, it does nothing.
331             sub my_static_handler {
332 26     26 0 55 my $attribute = shift();
333 26         51 my $flag = shift();
334              
335             ## checks to see if this debug level is set by a flag being passed in. If
336             ## the flag doesn't exist in our flags hash, then we can assume that
337             ## the flag variable isn't actually a flag, and is probably part of the
338             ## debug arguments... so put it back onto our args list.
339 26         73 my $debug_level = _is_flag_on($attribute, $flag);
340 26 100       76 if( not defined $debug_level ) {
341 14 50       69 unshift( @_, $flag ) if not defined $debug_level;
342             }
343              
344 26         207 my $full_package = (caller(2))[3];
345              
346 26         62 my $caller_sub_name = '';
347 26         110 GET_PROPER_PACKAGE_NAME: {
348 26         35 my @packages = split /::/, $full_package;
349 26         49 pop @packages;
350 26         77 $caller_sub_name = join '::', @packages;
351             }
352              
353 26 100       112 $debug_level = _is_attribute_on(
354             $attribute,
355             $full_package,
356             $caller_sub_name
357             ) if not $debug_level;
358              
359 26 100       91 return if not $debug_level;
360              
361              
362             ## we've got our debug level at this point, but we need to make sure that
363             ## there is an associated debug sub that matches the level. If not, then
364             ## we'll skip down till we find one.
365 14         21 my $executable;
366 14         43 while ( $debug_level ) {
367 27         287 $executable = $PACKAGE->can( "our${attribute}_". $debug_level--);
368 27 100       87 last if defined $executable;
369             }
370              
371 14 50       37 return if not defined $executable;
372            
373 14         68 return &$executable(@_);
374             }
375              
376              
377             sub _is_flag_on {
378 26     26   38 my $attribute = shift();
379 26 50       81 my $flag = shift() or return undef;
380              
381 26 100       127 return undef if not defined $ENABLE_FLAG->{$attribute}->{$flag};
382              
383 12   100     143 return $ENABLE_CHK->{$attribute}->{$ENABLE_ATTR->{$attribute} . "_$flag"} || 0;
384             }
385              
386              
387              
388             ##
389             ##
390             ## EEE OOOO FFFF
391             ##
392             ##
393              
394             =pod
395              
396             =head1 NAME
397              
398             Attribute::GlobalEnable - Enable Attrubutes and flags globally across all code.
399              
400             =head1 SYNOPSIS
401              
402             package Attribute::GlobalEnable::MyPackage;
403            
404             use Attibute::GlobalEnable(
405             ENABLE_CHK => \%ENV,
406             ENABLE_ATTR => { Debug => 'DEBUG_PERL' }
407             );
408            
409             ## see Attribute::Handlers for more info on these variables. Note
410             ## that this_package is not included in the list (because we're
411             ## calling it as a package method)
412             sub attrDebug_1 {
413             my $this_package = shift();
414             my $caller_package = shift();
415             my $code_symbol = shift();
416             my $code_ref = shift();
417             my $atribute = shift(); ## will be Debug ##
418             my $attribute_data = shift();
419             my $phase = shift();
420            
421             ## lets see what comes in and out ##
422             return sub {
423             warn "IN TO ". scalar( *$code_symbol )
424             . join "\n", @_;
425             my @data = &code_ref(@_);
426             warn "OUT FROM ". scalar( *$code_symbol )
427             . join "\n", @data;
428             return @data;
429             }
430             }
431            
432             sub ourTest_1 {
433             my $message = shift();
434             }
435            
436             1;
437            
438             ...
439             ...
440            
441             ## now, in your code: test_me.pl
442            
443            
444             sub my_funky_function : Debug {
445             my $self = shift();
446             my $var1 = shift();
447             my $var2 = shift();
448            
449             ## do some stuff ##
450             Debug( "VAR1: $var1" );
451             Debug( "VAR2: $var2" );
452             }
453            
454             ## since you've tied any debugging checks in to your env
455             ## you can turn MyPackage functionality on or off by setting
456             ## env vars with the special tag: DEBUG_PERL
457            
458             ## set it to level 1 for everything
459             %> ALL_DEBUG_PERL=1 ./test_me.pl
460             ## or
461             %> DEBUG_PERL=1 ./test_me.pl
462            
463             ## just for package 'main'
464             %> DEBUG_PERL_main=1 ./test_me.pl
465            
466             ## just for a single function
467             %> DEBUG_PERL_main__my_funky_function ./test_me.pl
468            
469             ## force it off for everyone
470             %> NO_DEBUG_PERL=1 ./test_me.pl
471              
472             =head1 DESCRIPTION
473              
474             Attribute::GlobalEnable provides switchable attribute hooks for all packages in
475             your namespace. It's primarily been developed with the idea of providing
476             debugging hooks that are very unobtrusive to the code. Since attributes
477             trigger their functionality at compile time (or at the least very early on,
478             before execution time), not enabling (or having your flags all off) does
479             nothing to the code. All the special functionality will be skipped, and
480             your code should operate like it wasn't there at all. It is, however,
481             not specific to debugging, so you can do what you wish with your attributes.
482              
483             Since all of the functionality of what your attributes do is defined by the
484             user (you), you MUST subpackage Attribute::GlobalEnable. It handles all of
485             the exporting for you, but you must format your hooks as explained below.
486              
487             Along with the special attribute functionality, the package also builds
488             special functions named the same as your attributes, and exports them to
489             which ever package 'use's your sub-package. Along with this, you can define
490             special flags that will turn this function on or off, and the flags play
491             with the rest of the system as one would expect.
492              
493             This package does not inherit from the Attribute class.
494              
495             =head1 FUNCTIONS
496              
497             There are no functions to use directly with this package. There are, however,
498             some special function names that YOU will define when subpackaging this, and
499             a package constructor where you do just that.
500              
501             =head2 Package Constructor
502              
503             This package is NOT an object. It is functional only. However, you must
504             initialize the package for use. The package is (more or less) a singleton,
505             so you can only initialize it once. DO NOT try to have multiple packages
506             set values, as it will just skip subsequent attempts to import past the
507             first one.
508              
509             There are 2 required keys, and 1 optional:
510              
511             =head3 (required) ENABLE_ATTR => $hash_ref
512              
513             This key is really the meat of it all, and the data you supply initializes
514             the attributes, and what functions it expects to see in your sub-package.
515             The structure of the hash is laid out as:
516              
517             {'Attribute_name' => 'SPECIAL_KEY', 'Attribute_name_2'... }
518              
519             The attribute name must be capitalized (see Attribute::Handlers), the
520             SPECIAL_KEY can be any string. You can have as many key => value pairs as
521             you deem necessary.
522              
523             Setting this value has multiple effects. First, it assigns the attribute
524             'Attribute_name' to a subroutine in the callers namespace, named:
525              
526             attr'Attribute_name'_#
527             ## ex: attrDebug_1
528              
529             The # should be an integer, and represents the number the SPECIAL_KEY has
530             been set to. More on that in a second tho. The attribute name is set in
531             the UNIVERSAL namespace, so now it can be utilized by everything under
532             your particular perl sun.
533              
534             What ever packages 'use' your sub-package, have another special subroutine
535             named 'Attribute_name' exported to their namespace. This subroutine points
536             to your sub-package subroutine named (similarly to above):
537              
538             our'Attribute_name'_#
539             ## ex: ourDebug_1
540              
541             The # should be an integer (see below for proper values) This function
542             can be turned on by the regular SPECIAL KEY, but also by any ENABLE_FLAGS
543             that you've defined as well... but more on that later.
544              
545             The 'SPECIAL_KEY' is the distinct identifier to trigger this attributes
546             functionality. It is not really meant to be used on it's own, (but it can).
547             It is mostly an identifier string that allows you to add stuff to it to
548             easily customize what you want to see (or do or whatever). There are 2
549             special pre-strings that you can slap on to the begining of the key:
550              
551             =over
552              
553             =item ALL_'SPECIAL_KEY' (or just 'SPECIAL_KEY')
554              
555             This turns the attributes functionality on for ALL of those subroutines that
556             have the attribute. This trumps all other settings, except for the NO_
557             pre-string.
558              
559             =item NO_'SPECIAL_KEY'
560              
561             This is essentially the default behaviour, turning the attribute stuff off.
562             This trumps everything... Other 'SPECIAL_KEY's, and any ENABLE_FLAGS.
563              
564             =back
565              
566             You can append package names, or even subroutines to the end of the
567             'SPECIAL_KEY', in order to turn the attribute functionality on for a specific
568             package or subroutine. Just separate the 'SPECIAL_KEY' and your specific
569             string with an underscore. Neato eh? There is one caveat to this. The regular
570             perl package (namespace) separator is replaced with two underscores, so if
571             you wanted to turn on attribute behaviour for MyPackage::ThisPackage, your
572             key would look like so:
573              
574             'SPECIAL_KEY'_MyPackage__ThisPacakge
575              
576             I did this so that you can just pass in the %ENV hash, and set your
577             attribute 'SPECIAL_KEY's on the command line or whathave you.
578              
579             Finally, the '#'s that you must name each of your special subs with, represent
580             a level for a particular functionality. This level is checked each time,
581             and the appropriate subroutine will be called, or it will try the next level
582             down. So, forexample: If you just have attr'Attribute_name'_1, but you set
583             your 'SPECIAL_KEY' to 3, then attr'Attribute_name'_1 will be executed.
584             if you had an attr'Attribute_name'_2, then that subroutine would be executed
585             instead of 1. This will not call each subroutine as it goes, it simply executes
586             the first one it finds.
587              
588              
589             =head3 (required) ENABLE_CHK => $hash_ref
590              
591             This must be set to a hash ref whos structure is laid out as:
592              
593             SOME_FLAG => $integer,
594              
595             $integer should be positive, and represents the attribute level you wish to
596             do attribute stuff at. (see ENABLEL_ATTR above for more info on that). The
597             actual hash can be empty, but the reference must exist.
598              
599             This represents the actual user set triggers for the attributes. Telling
600             GlobalEnable which to... well... enable, and which to skip.
601              
602             See the previous section for a description on special characters etc...
603              
604             =head3 ENABLE_FLAG => $hash_ref
605              
606             The $hash_ref structure must be:
607              
608             { Attribute_name => [ list of flags ], Attribute_name_2 ... }
609              
610             The ENABLE_FLAG is optional, and describes flags that can be set for the
611             exported 'Attribute_name' subroutines. These are exported as global
612             constants, so it looks nice and neat in your code. This essentially links
613             that sub call to that flag. The flag is still set like it would normally be
614             set in the ENABLE_CHK hash, however, you still must use the 'SPECIAL_KEY'
615             (see above) in the assignment, so your assignment will look like:
616              
617             'SPECIAL_KEY'_'FLAG'
618              
619             =head2 attr'Attribute_name'_#
620              
621             See ENABLE_ATTR above for a description on the layout naming scheme for this
622             particular subroutine name.
623              
624             This is your attribute hook for a particular level. This must return a
625             subroutine. The subroutine that it returns replaces the one the attribute is
626             currently assigned to. You can do anything you wish at this point, as you'll
627             have access to everything that's being passed in, everything that's being
628             passed out, and whatever else you want.
629              
630             It will always get these variables when it's called:
631              
632             =over
633              
634             =item [0] : package name ala $package->attr'Attribute_name'_1
635              
636             =item [1] : callers package name
637              
638             =item [2] : the code symbol (GLOB)
639              
640             =item [3] : the code reference of the sub that has this attribute turned on.
641              
642             =item [4] : the attribute name that triggered this.
643              
644             =item [5] : any attribute data assigned to the attribute.
645              
646             =item [6] : the current phase this was activated in.
647              
648             =back
649              
650             See perldoc Attribute::Handlers for more descirption on what these values
651             are, or how to utilize them.
652              
653             =head2 our'Attribute_name'_#
654              
655             This is the sub that's pointed to from our exported 'Attribute_name' subroutine.
656             If you pass in a valid flag, it'll clear that out before it sends the rest
657             of the arguments your way. There is no need to return a sub, as this is the
658             actual subroutine that's executed when you trigger this special sub.
659              
660             =head1 EXAMPLES
661              
662             For right now, see the tests for some examples. There's a test module in
663             the test dir as well. I'll fill in some examples a little later.
664              
665             =head1 SEE ALSO
666              
667             perldoc perlsub, Attribute::Handlers
668              
669             =head1 AUTHOR
670              
671             Craig Monson (cmonson [at the following]malachiarts com)
672              
673             =head1 ERRORS
674              
675             =over
676              
677             =item Must specify some arguments.
678              
679             You tried to init the package with nuttin. Gotta pass in some args.
680              
681             =item Must sub-package
682              
683             This isn't meant to be run on it's own.
684              
685             =item ENABLE_CHK needs to be set with a hash ref for this module to be used
686              
687             your ENABLE_CHK wasn't a hash ref. Please read this doc ;)
688              
689             =item ENABLE_ATTR must be set with a ref to a hash containing attribute names => key name.
690              
691             your ENABLE_ATTR was in the wrong format.
692              
693             =item 'blah' or 'blah' must be in valid format.
694              
695             Your key or value for ENABLE_ATTR wasn't in the right format.
696              
697             =item ENABLE_FLAG needs to be set with an array.
698              
699             If you're gonna set ENABLE_FLAG, the values for the keys must be array refs.
700              
701             =item Our eval failed: blah blah
702              
703             If you get this, then it's prolly a bug in the package. Please report it to
704             me.
705              
706             =back
707              
708             =head1 BUGS
709              
710            
711              
712             =head1 COPYRIGHT
713              
714             I suppose I (Craig Monson) own it. All Rights Reserved. This module is 100%
715             free software, and may be used, reused, redistributed, messed with,
716             subclassed, deleted, printed, compiled, and pooped on, just so long as you
717             follow the terms described by Perl itself.
718              
719             =cut
720              
721              
722              
723             1;
724