File Coverage

blib/lib/Venus/Core.pm
Criterion Covered Total %
statement 187 196 95.4
branch 27 36 75.0
condition 8 12 66.6
subroutine 41 42 97.6
pod 0 24 0.0
total 263 310 84.8


line stmt bran cond sub pod time code
1             package Venus::Core;
2              
3 87     61743   1546 use 5.018;
  87         286  
4              
5 87     28256   454 use strict;
  87         174  
  87         1796  
6 87     87   454 use warnings;
  87         183  
  87         12917  
7              
8             # METHODS
9              
10             sub ARGS {
11 17185     17185 0 35846 my ($self, @args) = @_;
12              
13             return (!@args)
14             ? ($self->DATA)
15             : ((@args == 1 && ref($args[0]) eq 'HASH')
16 17185 100 66     93068 ? (!%{$args[0]} ? $self->DATA : {%{$args[0]}})
  6865 50       16107  
  6861 100       33208  
    100          
17             : (@args % 2 ? {@args, undef} : {@args}));
18             }
19              
20             sub ATTR {
21 1800     1800 0 3640 my ($self, $attr, @args) = @_;
22              
23 87     87   716 no strict 'refs';
  87         205  
  87         3406  
24 87     87   536 no warnings 'redefine';
  87         206  
  87         27733  
25              
26 1524     155981   2643 *{"@{[$self->NAME]}::$attr"} = sub {$_[0]->ITEM($attr, @_[1..$#_])}
  1524         3382  
  155981         410580  
27 1800 100       15744 if !$self->can($attr);
28              
29 1800         3103 my $index = int(keys(%{$${"@{[$self->NAME]}::META"}{ATTR}})) + 1;
  1800         2259  
  1800         2385  
  1800         3254  
30              
31 1800         4630 $${"@{[$self->NAME]}::META"}{ATTR}{$attr} = [$index, [$attr, @args]];
  1800         2389  
  1800         3071  
32              
33 1800         3227 ${"@{[$self->NAME]}::@{[$self->METACACHE]}"} = undef;
  1800         2413  
  1800         3079  
  1800         3511  
34              
35 1800         3978 return $self;
36             }
37              
38             sub AUDIT {
39 2165     2165 0 3943 my ($self) = @_;
40              
41 2165         3384 return $self;
42             }
43              
44             sub BASE {
45 1003     1003 0 2905 my ($self, $base, @args) = @_;
46              
47 87     87   715 no strict 'refs';
  87         1820  
  87         33960  
48              
49 1003 100       1795 if (!grep !/\A[^:]+::\z/, keys(%{"${base}::"})) {
  1003         16044  
50 309 100       628 local $@; eval "require $base"; do{require Venus; Venus::fault($@)} if $@;
  309         17598  
  309         1925  
  1         5  
  1         8  
51             }
52              
53 1002         1965 @{"@{[$self->NAME]}::ISA"} = (
  1002         2158  
54 1002         2881 $base, (grep +($_ ne $base), @{"@{[$self->NAME]}::ISA"})
  1002         1767  
  1002         5385  
55             );
56              
57 1002         5037 my $index = int(keys(%{$${"@{[$self->NAME]}::META"}{BASE}})) + 1;
  1002         1643  
  1002         1780  
  1002         5780  
58              
59 1002         3221 $${"@{[$self->NAME]}::META"}{BASE}{$base} = [$index, [$base, @args]];
  1002         1626  
  1002         2039  
60              
61 1002         2205 ${"@{[$self->NAME]}::@{[$self->METACACHE]}"} = undef;
  1002         1664  
  1002         2069  
  1002         4172  
62              
63 1002         2949 return $self;
64             }
65              
66             sub BLESS {
67 16606     16606 0 34729 my ($self, @args) = @_;
68              
69 16606         40465 my $name = $self->NAME;
70 16606         61958 my $data = $self->DATA($self->ARGS($self->BUILDARGS(@args)));
71 16606         48482 my $anew = bless($data, $name);
72              
73 87     87   715 no strict 'refs';
  87         211  
  87         29664  
74              
75 16606         51763 $anew->BUILD($data);
76              
77             # FYI, every call to "new" calls "BUILD" which dispatches to each "BUILD"
78             # defined in each attached role.
79              
80             # If one (or more) roles use reflection (i.e. calls "META") to introspect the
81             # package's configuration, which could cause a performance problem given that
82             # the Venus::Meta class uses recursion to introspect all superclasses and
83             # roles to determine and present aggregate lists of package members. It's
84             # your classic n+1 problem.
85              
86             # The solution to this is to cache the associated Venus::Meta object which
87             # itself caches the results of its recursive lookups. The cache is stored on
88             # the subclass (i.e. on the calling package) and the cache will go away
89             # whenever the package does.
90              
91 16597 100 66     40486 ${"${name}::@{[$self->METACACHE]}"} ||= Venus::Meta->new(name => $name)
  13864         25901  
  13864         33090  
92             if $name ne 'Venus::Meta';
93              
94 16597         132791 return $anew;
95             }
96              
97             sub BUILD {
98 2749     2749 0 5168 my ($self) = @_;
99              
100 2749         4149 return $self;
101             }
102              
103             sub BUILDARGS {
104 3143     3143 0 7064 my ($self, @args) = @_;
105              
106 3143         8492 return (@args);
107             }
108              
109             sub DATA {
110 20010     20010 0 37307 my ($self, $data) = @_;
111              
112 20010 100       71627 return $data ? {%$data} : {};
113             }
114              
115             sub DESTROY {
116 2117     2117   4754 my ($self) = @_;
117              
118 2117         12000 return;
119             }
120              
121             sub DOES {
122 632     632 0 1425 my ($self, $role) = @_;
123              
124 632 50       2089 return if !$role;
125              
126 632         1829 return $self->META->role($role);
127             }
128              
129             sub EXPORT {
130 0     0 0 0 my ($self, $into) = @_;
131              
132 0         0 return [];
133             }
134              
135             sub FROM {
136 5     5 0 18 my ($self, $base) = @_;
137              
138 5         28 $self->BASE($base);
139              
140 5 50       46 $base->AUDIT($self->NAME) if $base->can('AUDIT');
141              
142 87     87   660 no warnings 'redefine';
  87         203  
  87         16702  
143              
144 5         18 $base->IMPORT($self->NAME);
145              
146 5         44 return $self;
147             }
148              
149             sub GET {
150 135680     135680 0 202083 my ($self, $name) = @_;
151              
152 135680         580697 return $self->{$name};
153             }
154              
155             sub IMPORT {
156 15     15 0 31 my ($self, $into) = @_;
157              
158 15         63 return $self;
159             }
160              
161             sub ITEM {
162 157016     157016 0 264901 my ($self, $name, @args) = @_;
163              
164 157016 50       265692 return undef if !$name;
165 157016 100       348604 return $self->GET($name) if !@args;
166 21337         49398 return $self->SET($name, $args[0]);
167             }
168              
169             sub META {
170 41247     41247 0 64234 my ($self) = @_;
171              
172 87     87   752 no strict 'refs';
  87         185  
  87         15930  
173              
174 41247         200679 require Venus::Meta;
175              
176 41247         81632 my $name = $self->NAME;
177              
178 41247   66     60260 return ${"${name}::@{[$self->METACACHE]}"}
179             || Venus::Meta->new(name => $name);
180             }
181              
182             sub METACACHE {
183 64447     64447 0 100847 my ($self) = @_;
184              
185 64447         366986 return 'METACACHE';
186             }
187              
188             sub MIXIN {
189 43     43 0 120 my ($self, $mixin, @args) = @_;
190              
191 87     87   632 no strict 'refs';
  87         206  
  87         12109  
192              
193 43 50       83 if (!grep !/\A[^:]+::\z/, keys(%{"${mixin}::"})) {
  43         461  
194 0 0       0 local $@; eval "require $mixin"; do{require Venus; Venus::fault($@)} if $@;
  0         0  
  0         0  
  0         0  
  0         0  
195             }
196              
197 87     87   629 no warnings 'redefine';
  87         177  
  87         5322  
198              
199 43         160 $mixin->IMPORT($self->NAME);
200              
201 87     87   655 no strict 'refs';
  87         182  
  87         18367  
202              
203 43         65 my $index = int(keys(%{$${"@{[$self->NAME]}::META"}{MIXIN}})) + 1;
  43         55  
  43         74  
  43         87  
204              
205 43         135 $${"@{[$self->NAME]}::META"}{MIXIN}{$mixin} = [$index, [$mixin, @args]];
  43         59  
  43         88  
206              
207 43         103 ${"@{[$self->NAME]}::@{[$self->METACACHE]}"} = undef;
  43         68  
  43         77  
  43         102  
208              
209 43         147 return $self;
210             }
211              
212             sub NAME {
213 92667     92667 0 144199 my ($self) = @_;
214              
215 92667   66     384867 return ref $self || $self;
216             }
217              
218             sub ROLE {
219 3170     3170 0 8161 my ($self, $role, @args) = @_;
220              
221 87     87   696 no strict 'refs';
  87         211  
  87         11821  
222              
223 3170 100       4579 if (!grep !/\A[^:]+::\z/, keys(%{"${role}::"})) {
  3170         26862  
224 1860 50       3328 local $@; eval "require $role"; do{require Venus; Venus::fault($@)} if $@;
  1860         104545  
  1860         9866  
  0         0  
  0         0  
225             }
226              
227 87     87   698 no warnings 'redefine';
  87         236  
  87         4502  
228              
229 3170         14042 $role->IMPORT($self->NAME);
230              
231 87     87   609 no strict 'refs';
  87         201  
  87         19454  
232              
233 3170         4624 my $index = int(keys(%{$${"@{[$self->NAME]}::META"}{ROLE}})) + 1;
  3170         4027  
  3170         4209  
  3170         5969  
234              
235 3170         8210 $${"@{[$self->NAME]}::META"}{ROLE}{$role} = [$index, [$role, @args]];
  3170         4381  
  3170         5468  
236              
237 3170         5973 ${"@{[$self->NAME]}::@{[$self->METACACHE]}"} = undef;
  3170         4168  
  3170         5533  
  3170         7154  
238              
239 3170         5960 return $self;
240             }
241              
242             sub SET {
243 21338     21338 0 36700 my ($self, $name, $data) = @_;
244              
245 21338         57876 return $self->{$name} = $data;
246             }
247              
248             sub SUBS {
249 1     1 0 3 my ($self) = @_;
250              
251 87     87   658 no strict 'refs';
  87         258  
  87         36260  
252              
253             return [
254 11         14 sort grep *{"@{[$self->NAME]}::$_"}{"CODE"},
  11         16  
255 1         6 grep /^[_a-zA-Z]\w*$/, keys %{"@{[$self->NAME]}::"}
  1         7  
  1         3  
256             ];
257             }
258              
259             sub TEST {
260 3149     3149 0 5780 my ($self, $role) = @_;
261              
262 3149         9461 $self->ROLE($role);
263              
264 3149 50       23976 $role->AUDIT($self->NAME) if $role->can('AUDIT');
265              
266 3145         6957 return $self;
267             }
268              
269             sub UNIMPORT {
270 1     1 0 5 my ($self, $into, @args) = @_;
271              
272 1         8 return $self;
273             }
274              
275             sub USE {
276 3021     3021 0 6964 my ($self, $into, @args) = @_;
277              
278 3021         6654 return $self;
279             }
280              
281             1;
282              
283              
284              
285             =head1 NAME
286              
287             Venus::Core - Core Base Class
288              
289             =cut
290              
291             =head1 ABSTRACT
292              
293             Core Base Class for Perl 5
294              
295             =cut
296              
297             =head1 SYNOPSIS
298              
299             package User;
300              
301             use base 'Venus::Core';
302              
303             package main;
304              
305             my $user = User->BLESS(
306             fname => 'Elliot',
307             lname => 'Alderson',
308             );
309              
310             # bless({fname => 'Elliot', lname => 'Alderson'}, 'User')
311              
312             # i.e. BLESS is somewhat equivalent to writing
313              
314             # User->BUILD(bless(User->ARGS(User->BUILDARGS(@args) || User->DATA), 'User'))
315              
316             =cut
317              
318             =head1 DESCRIPTION
319              
320             This package provides a base class for L<"class"|Venus::Core::Class> and
321             L<"role"|Venus::Core::Role> (kind) derived packages and provides class building,
322             object construction, and object deconstruction lifecycle hooks. The
323             L and L packages provide a simple DSL for automating
324             L derived base classes.
325              
326             =cut
327              
328             =head1 METHODS
329              
330             This package provides the following methods:
331              
332             =cut
333              
334             =head2 args
335              
336             ARGS(Any @args) (HashRef)
337              
338             The ARGS method is a object construction lifecycle hook which accepts a list of
339             arguments and returns a blessable data structure.
340              
341             I>
342              
343             =over 4
344              
345             =item args example 1
346              
347             # given: synopsis
348              
349             package main;
350              
351             my $args = User->ARGS;
352              
353             # {}
354              
355             =back
356              
357             =over 4
358              
359             =item args example 2
360              
361             # given: synopsis
362              
363             package main;
364              
365             my $args = User->ARGS(name => 'Elliot');
366              
367             # {name => 'Elliot'}
368              
369             =back
370              
371             =over 4
372              
373             =item args example 3
374              
375             # given: synopsis
376              
377             package main;
378              
379             my $args = User->ARGS({name => 'Elliot'});
380              
381             # {name => 'Elliot'}
382              
383             =back
384              
385             =cut
386              
387             =head2 attr
388              
389             ATTR(Str $name, Any @args) (Str | Object)
390              
391             The ATTR method is a class building lifecycle hook which installs an attribute
392             accessors in the calling package.
393              
394             I>
395              
396             =over 4
397              
398             =item attr example 1
399              
400             package User;
401              
402             use base 'Venus::Core';
403              
404             User->ATTR('name');
405              
406             package main;
407              
408             my $user = User->BLESS;
409              
410             # bless({}, 'User')
411              
412             # $user->name;
413              
414             # ""
415              
416             # $user->name('Elliot');
417              
418             # "Elliot"
419              
420             =back
421              
422             =over 4
423              
424             =item attr example 2
425              
426             package User;
427              
428             use base 'Venus::Core';
429              
430             User->ATTR('role');
431              
432             package main;
433              
434             my $user = User->BLESS(role => 'Engineer');
435              
436             # bless({role => 'Engineer'}, 'User')
437              
438             # $user->role;
439              
440             # "Engineer"
441              
442             # $user->role('Hacker');
443              
444             # "Hacker"
445              
446             =back
447              
448             =cut
449              
450             =head2 audit
451              
452             AUDIT(Str $role) (Str | Object)
453              
454             The AUDIT method is a class building lifecycle hook which exist in roles and is
455             executed as a callback when the consuming class invokes the L hook.
456              
457             I>
458              
459             =over 4
460              
461             =item audit example 1
462              
463             package HasType;
464              
465             use base 'Venus::Core';
466              
467             sub AUDIT {
468             die 'Consumer missing "type" attribute' if !$_[1]->can('type');
469             }
470              
471             package User;
472              
473             use base 'Venus::Core';
474              
475             User->TEST('HasType');
476              
477             package main;
478              
479             my $user = User->BLESS;
480              
481             # Exception! Consumer missing "type" attribute
482              
483             =back
484              
485             =over 4
486              
487             =item audit example 2
488              
489             package HasType;
490              
491             sub AUDIT {
492             die 'Consumer missing "type" attribute' if !$_[1]->can('type');
493             }
494              
495             package User;
496              
497             use base 'Venus::Core';
498              
499             User->ATTR('type');
500              
501             User->TEST('HasType');
502              
503             package main;
504              
505             my $user = User->BLESS;
506              
507             # bless({}, 'User')
508              
509             =back
510              
511             =cut
512              
513             =head2 base
514              
515             BASE(Str $name) (Str | Object)
516              
517             The BASE method is a class building lifecycle hook which registers a base class
518             for the calling package. B Unlike the L hook, this hook doesn't
519             invoke the L hook.
520              
521             I>
522              
523             =over 4
524              
525             =item base example 1
526              
527             package Entity;
528              
529             sub work {
530             return;
531             }
532              
533             package User;
534              
535             use base 'Venus::Core';
536              
537             User->BASE('Entity');
538              
539             package main;
540              
541             my $user = User->BLESS;
542              
543             # bless({}, 'User')
544              
545             =back
546              
547             =over 4
548              
549             =item base example 2
550              
551             package Engineer;
552              
553             sub debug {
554             return;
555             }
556              
557             package Entity;
558              
559             sub work {
560             return;
561             }
562              
563             package User;
564              
565             use base 'Venus::Core';
566              
567             User->BASE('Entity');
568              
569             User->BASE('Engineer');
570              
571             package main;
572              
573             my $user = User->BLESS;
574              
575             # bless({}, 'User')
576              
577             =back
578              
579             =over 4
580              
581             =item base example 3
582              
583             package User;
584              
585             use base 'Venus::Core';
586              
587             User->BASE('Manager');
588              
589             # Exception! "Can't locate Manager.pm in @INC"
590              
591             =back
592              
593             =cut
594              
595             =head2 bless
596              
597             BLESS(Any @args) (Object)
598              
599             The BLESS method is an object construction lifecycle hook which returns an
600             instance of the calling package.
601              
602             I>
603              
604             =over 4
605              
606             =item bless example 1
607              
608             package User;
609              
610             use base 'Venus::Core';
611              
612             package main;
613              
614             my $example = User->BLESS;
615              
616             # bless({}, 'User')
617              
618             =back
619              
620             =over 4
621              
622             =item bless example 2
623              
624             package User;
625              
626             use base 'Venus::Core';
627              
628             package main;
629              
630             my $example = User->BLESS(name => 'Elliot');
631              
632             # bless({name => 'Elliot'}, 'User')
633              
634             =back
635              
636             =over 4
637              
638             =item bless example 3
639              
640             package User;
641              
642             use base 'Venus::Core';
643              
644             package main;
645              
646             my $example = User->BLESS({name => 'Elliot'});
647              
648             # bless({name => 'Elliot'}, 'User')
649              
650             =back
651              
652             =over 4
653              
654             =item bless example 4
655              
656             package List;
657              
658             use base 'Venus::Core';
659              
660             sub ARGS {
661             my ($self, @args) = @_;
662              
663             return @args
664             ? ((@args == 1 && ref $args[0] eq 'ARRAY') ? @args : [@args])
665             : $self->DATA;
666             }
667              
668             sub DATA {
669             my ($self, $data) = @_;
670              
671             return $data ? [@$data] : [];
672             }
673              
674             package main;
675              
676             my $list = List->BLESS(1..4);
677              
678             # bless([1..4], 'List')
679              
680             =back
681              
682             =over 4
683              
684             =item bless example 5
685              
686             package List;
687              
688             use base 'Venus::Core';
689              
690             sub ARGS {
691             my ($self, @args) = @_;
692              
693             return @args
694             ? ((@args == 1 && ref $args[0] eq 'ARRAY') ? @args : [@args])
695             : $self->DATA;
696             }
697              
698             sub DATA {
699             my ($self, $data) = @_;
700              
701             return $data ? [@$data] : [];
702             }
703              
704             package main;
705              
706             my $list = List->BLESS([1..4]);
707              
708             # bless([1..4], 'List')
709              
710             =back
711              
712             =cut
713              
714             =head2 build
715              
716             BUILD(HashRef $data) (Object)
717              
718             The BUILD method is an object construction lifecycle hook which receives an
719             object and the data structure that was blessed, and should return an object
720             although its return value is ignored by the L hook.
721              
722             I>
723              
724             =over 4
725              
726             =item build example 1
727              
728             package User;
729              
730             use base 'Venus::Core';
731              
732             sub BUILD {
733             my ($self) = @_;
734              
735             $self->{name} = 'Mr. Robot';
736              
737             return $self;
738             }
739              
740             package main;
741              
742             my $example = User->BLESS(name => 'Elliot');
743              
744             # bless({name => 'Mr. Robot'}, 'User')
745              
746             =back
747              
748             =over 4
749              
750             =item build example 2
751              
752             package User;
753              
754             use base 'Venus::Core';
755              
756             sub BUILD {
757             my ($self) = @_;
758              
759             $self->{name} = 'Mr. Robot';
760              
761             return $self;
762             }
763              
764             package Elliot;
765              
766             use base 'User';
767              
768             sub BUILD {
769             my ($self, $data) = @_;
770              
771             $self->SUPER::BUILD($data);
772              
773             $self->{name} = 'Elliot';
774              
775             return $self;
776             }
777              
778             package main;
779              
780             my $elliot = Elliot->BLESS;
781              
782             # bless({name => 'Elliot'}, 'Elliot')
783              
784             =back
785              
786             =cut
787              
788             =head2 buildargs
789              
790             BUILDARGS(Any @args) (Any @args | HashRef $data)
791              
792             The BUILDARGS method is an object construction lifecycle hook which receives
793             the arguments provided to the constructor (unaltered) and should return a list
794             of arguments, a hashref, or key/value pairs.
795              
796             I>
797              
798             =over 4
799              
800             =item buildargs example 1
801              
802             package User;
803              
804             use base 'Venus::Core';
805              
806             sub BUILD {
807             my ($self) = @_;
808              
809             return $self;
810             }
811              
812             sub BUILDARGS {
813             my ($self, @args) = @_;
814              
815             my $data = @args == 1 && !ref $args[0] ? {name => $args[0]} : {};
816              
817             return $data;
818             }
819              
820             package main;
821              
822             my $user = User->BLESS('Elliot');
823              
824             # bless({name => 'Elliot'}, 'User')
825              
826             =back
827              
828             =cut
829              
830             =head2 data
831              
832             DATA() (Ref)
833              
834             The DATA method is an object construction lifecycle hook which returns the
835             default data structure reference to be blessed when no arguments are provided
836             to the constructor. The default data structure is an empty hashref.
837              
838             I>
839              
840             =over 4
841              
842             =item data example 1
843              
844             package Example;
845              
846             use base 'Venus::Core';
847              
848             sub DATA {
849             return [];
850             }
851              
852             package main;
853              
854             my $example = Example->BLESS;
855              
856             # bless([], 'Example')
857              
858             =back
859              
860             =over 4
861              
862             =item data example 2
863              
864             package Example;
865              
866             use base 'Venus::Core';
867              
868             sub DATA {
869             return {};
870             }
871              
872             package main;
873              
874             my $example = Example->BLESS;
875              
876             # bless({}, 'Example')
877              
878             =back
879              
880             =cut
881              
882             =head2 destroy
883              
884             DESTROY() (Any)
885              
886             The DESTROY method is an object destruction lifecycle hook which is called when
887             the last reference to the object goes away.
888              
889             I>
890              
891             =over 4
892              
893             =item destroy example 1
894              
895             package User;
896              
897             use base 'Venus::Core';
898              
899             our $USERS = 0;
900              
901             sub BUILD {
902             return $USERS++;
903             }
904              
905             sub DESTROY {
906             return $USERS--;
907             }
908              
909             package main;
910              
911             my $user = User->BLESS(name => 'Elliot');
912              
913             undef $user;
914              
915             # undef
916              
917             =back
918              
919             =cut
920              
921             =head2 does
922              
923             DOES(Str $name) (Bool)
924              
925             The DOES method returns true or false if the invocant consumed the role or
926             interface provided.
927              
928             I>
929              
930             =over 4
931              
932             =item does example 1
933              
934             package Admin;
935              
936             use base 'Venus::Core';
937              
938             package User;
939              
940             use base 'Venus::Core';
941              
942             User->ROLE('Admin');
943              
944             sub BUILD {
945             my ($self) = @_;
946              
947             return $self;
948             }
949              
950             sub BUILDARGS {
951             my ($self, @args) = @_;
952              
953             return (@args);
954             }
955              
956             package main;
957              
958             my $admin = User->DOES('Admin');
959              
960             # 1
961              
962             =back
963              
964             =over 4
965              
966             =item does example 2
967              
968             package Admin;
969              
970             use base 'Venus::Core';
971              
972             package User;
973              
974             use base 'Venus::Core';
975              
976             User->ROLE('Admin');
977              
978             sub BUILD {
979             my ($self) = @_;
980              
981             return $self;
982             }
983              
984             sub BUILDARGS {
985             my ($self, @args) = @_;
986              
987             return (@args);
988             }
989              
990             package main;
991              
992             my $is_owner = User->DOES('Owner');
993              
994             # 0
995              
996             =back
997              
998             =cut
999              
1000             =head2 export
1001              
1002             EXPORT(Any @args) (ArrayRef)
1003              
1004             The EXPORT method is a class building lifecycle hook which returns an arrayref
1005             of routine names to be automatically imported by the calling package whenever
1006             the L or L hooks are used.
1007              
1008             I>
1009              
1010             =over 4
1011              
1012             =item export example 1
1013              
1014             package Admin;
1015              
1016             use base 'Venus::Core';
1017              
1018             sub shutdown {
1019             return;
1020             }
1021              
1022             sub EXPORT {
1023             ['shutdown']
1024             }
1025              
1026             package User;
1027              
1028             use base 'Venus::Core';
1029              
1030             User->ROLE('Admin');
1031              
1032             package main;
1033              
1034             my $user = User->BLESS;
1035              
1036             # bless({}, 'User')
1037              
1038             =back
1039              
1040             =cut
1041              
1042             =head2 from
1043              
1044             FROM(Str $name) (Str | Object)
1045              
1046             The FROM method is a class building lifecycle hook which registers a base class
1047             for the calling package, automatically invoking the L and L
1048             hooks on the base class.
1049              
1050             I>
1051              
1052             =over 4
1053              
1054             =item from example 1
1055              
1056             package Entity;
1057              
1058             use base 'Venus::Core';
1059              
1060             sub AUDIT {
1061             my ($self, $from) = @_;
1062             die "Missing startup" if !$from->can('startup');
1063             die "Missing shutdown" if !$from->can('shutdown');
1064             }
1065              
1066             package User;
1067              
1068             use base 'Venus::Core';
1069              
1070             User->ATTR('startup');
1071             User->ATTR('shutdown');
1072              
1073             User->FROM('Entity');
1074              
1075             package main;
1076              
1077             my $user = User->BLESS;
1078              
1079             # bless({}, 'User')
1080              
1081             =back
1082              
1083             =over 4
1084              
1085             =item from example 2
1086              
1087             package Entity;
1088              
1089             use base 'Venus::Core';
1090              
1091             sub AUDIT {
1092             my ($self, $from) = @_;
1093             die "Missing startup" if !$from->can('startup');
1094             die "Missing shutdown" if !$from->can('shutdown');
1095             }
1096              
1097             package User;
1098              
1099             use base 'Venus::Core';
1100              
1101             User->FROM('Entity');
1102              
1103             sub startup {
1104             return;
1105             }
1106              
1107             sub shutdown {
1108             return;
1109             }
1110              
1111             package main;
1112              
1113             my $user = User->BLESS;
1114              
1115             # bless({}, 'User')
1116              
1117             =back
1118              
1119             =cut
1120              
1121             =head2 get
1122              
1123             GET(Str $name) (Any)
1124              
1125             The GET method is a class instance lifecycle hook which is responsible for
1126             I<"getting"> instance items (or attribute values). By default, all class
1127             attributes I<"getters"> are dispatched to this method.
1128              
1129             I>
1130              
1131             =over 4
1132              
1133             =item get example 1
1134              
1135             package User;
1136              
1137             use base 'Venus::Core';
1138              
1139             User->ATTR('name');
1140              
1141             package main;
1142              
1143             my $user = User->BLESS(title => 'Engineer');
1144              
1145             # bless({title => 'Engineer'}, 'User')
1146              
1147             my $get = $user->GET('title');
1148              
1149             # "Engineer"
1150              
1151             =back
1152              
1153             =cut
1154              
1155             =head2 import
1156              
1157             IMPORT(Str $into, Any @args) (Str | Object)
1158              
1159             The IMPORT method is a class building lifecycle hook which dispatches the
1160             L lifecycle hook whenever the L or L hooks are used.
1161              
1162             I>
1163              
1164             =over 4
1165              
1166             =item import example 1
1167              
1168             package Admin;
1169              
1170             use base 'Venus::Core';
1171              
1172             our $USES = 0;
1173              
1174             sub shutdown {
1175             return;
1176             }
1177              
1178             sub EXPORT {
1179             ['shutdown']
1180             }
1181              
1182             sub IMPORT {
1183             my ($self, $into) = @_;
1184              
1185             $self->SUPER::IMPORT($into);
1186              
1187             $USES++;
1188              
1189             return $self;
1190             }
1191              
1192             package User;
1193              
1194             use base 'Venus::Core';
1195              
1196             User->ROLE('Admin');
1197              
1198             package main;
1199              
1200             my $user = User->BLESS;
1201              
1202             # bless({}, 'User')
1203              
1204             =back
1205              
1206             =cut
1207              
1208             =head2 item
1209              
1210             ITEM(Str $name, Any @args) (Str | Object)
1211              
1212             The ITEM method is a class instance lifecycle hook which is responsible for
1213             I<"getting"> and I<"setting"> instance items (or attributes). By default, all
1214             class attributes are dispatched to this method.
1215              
1216             I>
1217              
1218             =over 4
1219              
1220             =item item example 1
1221              
1222             package User;
1223              
1224             use base 'Venus::Core';
1225              
1226             User->ATTR('name');
1227              
1228             package main;
1229              
1230             my $user = User->BLESS;
1231              
1232             # bless({}, 'User')
1233              
1234             my $item = $user->ITEM('name', 'unknown');
1235              
1236             # "unknown"
1237              
1238             =back
1239              
1240             =over 4
1241              
1242             =item item example 2
1243              
1244             package User;
1245              
1246             use base 'Venus::Core';
1247              
1248             User->ATTR('name');
1249              
1250             package main;
1251              
1252             my $user = User->BLESS;
1253              
1254             # bless({}, 'User')
1255              
1256             $user->ITEM('name', 'known');
1257              
1258             my $item = $user->ITEM('name');
1259              
1260             # "known"
1261              
1262             =back
1263              
1264             =cut
1265              
1266             =head2 meta
1267              
1268             META() (Meta)
1269              
1270             The META method return a L object which describes the invocant's
1271             configuration.
1272              
1273             I>
1274              
1275             =over 4
1276              
1277             =item meta example 1
1278              
1279             package User;
1280              
1281             use base 'Venus::Core';
1282              
1283             package main;
1284              
1285             my $meta = User->META;
1286              
1287             # bless({name => 'User'}, 'Venus::Meta')
1288              
1289             =back
1290              
1291             =cut
1292              
1293             =head2 name
1294              
1295             NAME() (Str)
1296              
1297             The NAME method is a class building lifecycle hook which returns the name of
1298             the package.
1299              
1300             I>
1301              
1302             =over 4
1303              
1304             =item name example 1
1305              
1306             package User;
1307              
1308             use base 'Venus::Core';
1309              
1310             package main;
1311              
1312             my $name = User->NAME;
1313              
1314             # "User"
1315              
1316             =back
1317              
1318             =over 4
1319              
1320             =item name example 2
1321              
1322             package User;
1323              
1324             use base 'Venus::Core';
1325              
1326             package main;
1327              
1328             my $name = User->BLESS->NAME;
1329              
1330             # "User"
1331              
1332             =back
1333              
1334             =cut
1335              
1336             =head2 role
1337              
1338             ROLE(Str $name) (Str | Object)
1339              
1340             The ROLE method is a class building lifecycle hook which consumes the role
1341             provided, automatically invoking the role's L hook. B Unlike
1342             the L and L hooks, this hook doesn't invoke the L hook.
1343             The role composition semantics are as follows: Routines to be consumed must be
1344             explicitly declared via the L hook. Routines will be copied to the
1345             consumer unless they already exist (excluding routines from base classes, which
1346             will be overridden). If multiple roles are consumed having routines with the
1347             same name (i.e. naming collisions) the first routine copied wins.
1348              
1349             I>
1350              
1351             =over 4
1352              
1353             =item role example 1
1354              
1355             package Admin;
1356              
1357             use base 'Venus::Core';
1358              
1359             package User;
1360              
1361             use base 'Venus::Core';
1362              
1363             User->ROLE('Admin');
1364              
1365             package main;
1366              
1367             my $admin = User->DOES('Admin');
1368              
1369             # 1
1370              
1371             =back
1372              
1373             =over 4
1374              
1375             =item role example 2
1376              
1377             package Create;
1378              
1379             use base 'Venus::Core';
1380              
1381             package Delete;
1382              
1383             use base 'Venus::Core';
1384              
1385             package Manage;
1386              
1387             use base 'Venus::Core';
1388              
1389             Manage->ROLE('Create');
1390             Manage->ROLE('Delete');
1391              
1392             package User;
1393              
1394             use base 'Venus::Core';
1395              
1396             User->ROLE('Manage');
1397              
1398             package main;
1399              
1400             my $create = User->DOES('Create');
1401              
1402             # 1
1403              
1404             =back
1405              
1406             =cut
1407              
1408             =head2 set
1409              
1410             SET(Str $name, Any @args) (Any)
1411              
1412             The SET method is a class instance lifecycle hook which is responsible for
1413             I<"setting"> instance items (or attribute values). By default, all class
1414             attributes I<"setters"> are dispatched to this method.
1415              
1416             =over 4
1417              
1418             =item set example 1
1419              
1420             package User;
1421              
1422             use base 'Venus::Core';
1423              
1424             User->ATTR('name');
1425              
1426             package main;
1427              
1428             my $user = User->BLESS(title => 'Engineer');
1429              
1430             # bless({title => 'Engineer'}, 'User')
1431              
1432             my $set = $user->SET('title', 'Manager');
1433              
1434             # "Manager"
1435              
1436             =back
1437              
1438             =cut
1439              
1440             =head2 subs
1441              
1442             SUBS() (ArrayRef)
1443              
1444             The SUBS method returns the routines defined on the package and consumed from
1445             roles, but not inherited by superclasses.
1446              
1447             I>
1448              
1449             =over 4
1450              
1451             =item subs example 1
1452              
1453             package Example;
1454              
1455             use base 'Venus::Core';
1456              
1457             package main;
1458              
1459             my $subs = Example->SUBS;
1460              
1461             # [...]
1462              
1463             =back
1464              
1465             =cut
1466              
1467             =head2 test
1468              
1469             TEST(Str $name) (Str | Object)
1470              
1471             The TEST method is a class building lifecycle hook which consumes the role
1472             provided, automatically invoking the role's L hook as well as the
1473             L hook if defined.
1474              
1475             I>
1476              
1477             =over 4
1478              
1479             =item test example 1
1480              
1481             package Admin;
1482              
1483             use base 'Venus::Core';
1484              
1485             package IsAdmin;
1486              
1487             use base 'Venus::Core';
1488              
1489             sub shutdown {
1490             return;
1491             }
1492              
1493             sub AUDIT {
1494             my ($self, $from) = @_;
1495             die "${from} is not a super-user" if !$from->DOES('Admin');
1496             }
1497              
1498             sub EXPORT {
1499             ['shutdown']
1500             }
1501              
1502             package User;
1503              
1504             use base 'Venus::Core';
1505              
1506             User->ROLE('Admin');
1507              
1508             User->TEST('IsAdmin');
1509              
1510             package main;
1511              
1512             my $user = User->BLESS;
1513              
1514             # bless({}, 'User')
1515              
1516             =back
1517              
1518             =cut
1519              
1520             =head2 unimport
1521              
1522             UNIMPORT(Str $into, Any @args) (Any)
1523              
1524             The UNIMPORT method is a class building lifecycle hook which is invoked
1525             whenever the L declaration is used.
1526              
1527             I>
1528              
1529             =over 4
1530              
1531             =item unimport example 1
1532              
1533             package User;
1534              
1535             use base 'Venus::Core';
1536              
1537             package main;
1538              
1539             User->UNIMPORT;
1540              
1541             # 'User'
1542              
1543             =back
1544              
1545             =cut
1546              
1547             =head1 AUTHORS
1548              
1549             Awncorp, C
1550              
1551             =cut
1552              
1553             =head1 LICENSE
1554              
1555             Copyright (C) 2000, Al Newkirk.
1556              
1557             This program is free software, you can redistribute it and/or modify it under
1558             the terms of the Apache license version 2.0.
1559              
1560             =cut