File Coverage

blib/lib/aliased/factory.pm
Criterion Covered Total %
statement 39 41 95.1
branch 12 18 66.6
condition n/a
subroutine 10 10 100.0
pod 2 2 100.0
total 63 71 88.7


line stmt bran cond sub pod time code
1             package aliased::factory;
2             $VERSION = v0.0.1;
3              
4 2     2   43174 use warnings;
  2         4  
  2         72  
5 2     2   12 use strict;
  2         3  
  2         232  
6 2     2   24 use Carp;
  2         4  
  2         1080  
7              
8             =head1 NAME
9              
10             aliased::factory - shorter versions of a class tree's constructors
11              
12             =head1 SYNOPSIS
13              
14             use aliased::factory YAPI => 'Yahoo::Marketing';
15              
16             my $service = YAPI->KeywordResearchService->new(...);
17              
18             my $res = $service->getRelatedKeywords(
19             relatedKeywordRequest =>
20             YAPI->RelatedKeywordRequestType->new(...)
21             );
22              
23             =head1 About
24              
25             This package is similar to L, but performs on-demand loading
26             for packages below the shortened 'root package'. For example, the above
27             code will automatically load the KeywordResearchService and
28             RelatedKeywordRequestType packages from the Yahoo::Marketing::
29             hierarchy.
30              
31             To load a second-level package:
32              
33             use aliased::factory BAR => 'Foo::Bar';
34              
35             my $bort = BAR->Baz->Bort->new(...);
36              
37             This would load the Foo::Bar::Baz and then Foo::Bar::Baz::Bort packages.
38             Each method call require()s the corresponding package and returns an
39             aliased::factory object, which has a new() method (see below.)
40              
41             =cut
42              
43             my $new_factory = sub {
44             my $class = shift;
45             bless \(shift) => $class;
46             };
47              
48             my $err;
49              
50             my $load = sub {
51             my $package = shift;
52             $package =~ s#::#/#g;
53             $package .= '.pm';
54             return 1 if(exists $INC{$package});
55              
56             local $@;
57             my $ans = eval {require($package)};
58             if($err = $@) {
59             my $f = __FILE__;
60             ($err = $@) =~ s/ at $f line \d+\.\n//;
61             return;
62             }
63              
64             return($ans);
65             };
66              
67             =head1 Factory Method
68              
69             =head2 new
70              
71             Returns a new object of the class represented by the $factory object.
72              
73             my $instantiated = $factory->new(...);
74              
75             The class being instantiated must have a new() method.
76              
77             =cut
78              
79             sub new {
80 7     7 1 12 my $self = shift;
81 7         67 return $$self->new(@_);
82             } ######################################################################
83              
84             =head1 Meta Methods
85              
86             The rest of this is functionality used to create the factory.
87              
88             =head2 import
89              
90             Installs a sub 'shortname' in your package containing an object pointed
91             at $package.
92              
93             aliased::factory->import(shortname => $package);
94              
95             =cut
96              
97             sub import {
98 2     2   42 my $class = shift;
99 2 100       20 @_ or return;
100              
101 1         3 my ($alias, $package, @also) = @_;
102 1 50       3 croak("error") if(@also);
103              
104 1         2 my $caller = caller;
105              
106 1 50       5 unless(defined $package) {
107 0         0 $package = $alias;
108 0         0 $alias =~ s/.*:://;
109             }
110              
111 1 50       4 $load->($package) or croak($err);
112              
113 1         3 my $obj = $class->$new_factory($package);
114 2     2   14 no strict 'refs';
  2         4  
  2         687  
115 1     10   3 *{$caller . '::' . $alias} = sub { $obj };
  1         2367  
  10         5872  
116             } ######################################################################
117              
118             =head2 can
119              
120             When called on a factory object, attempts to require the subpackage. If
121             this succeeds, it will return a coderef (which will return the
122             subfactory when executed.)
123              
124             my $coderef = $factory->can('subpackage');
125              
126             This method is used by AUTOLOAD().
127              
128             =cut
129              
130             sub can {
131 15     15 1 20 my $self = shift;
132 15 50       39 my $class = ref($self) or return($self->SUPER::can(@_));
133 15         22 my ($subpack) = @_;
134              
135 15         34 my $package = $$self . '::' . $subpack;
136 15 100       23 $load->($package) or return;
137 11         24 my $obj = $class->$new_factory($package);
138 11     11   67 return sub {$obj};
  11         69  
139             } ######################################################################
140              
141             =head2 AUTOLOAD
142              
143             Attempts to load the $factory's corresponding subpackage, returns a the
144             subfactory object or throws a fatal error: "Can't locate ... in @INC
145             ...".
146              
147             my $subfactory = $factory->subpackage;
148              
149             =cut
150              
151             sub AUTOLOAD {
152 11     11   18 my $self = shift;
153 11 50       34 @_ and croak("subfactories cannot have arguments");
154              
155 11         54 (my $method = our $AUTOLOAD) =~ s/.*:://;
156 11 50       34 return if $method eq 'DESTROY';
157 11 100       21 my $sub = $self->can($method) or croak($err);
158 10         19 return $sub->();
159             } ######################################################################
160              
161             =head1 AUTHOR
162              
163             Eric Wilhelm @
164              
165             http://scratchcomputing.com/
166              
167             =head1 BUGS
168              
169             If you found this module on CPAN, please report any bugs or feature
170             requests through the web interface at L. I will be
171             notified, and then you'll automatically be notified of progress on your
172             bug as I make changes.
173              
174             If you pulled this development version from my /svn/, please contact me
175             directly.
176              
177             =head1 COPYRIGHT
178              
179             Copyright (C) 2009 Eric L. Wilhelm, All Rights Reserved.
180              
181             =head1 Acknowledgements
182              
183             Thanks to HDP for the suggestion of using a factory object.
184              
185             =head1 NO WARRANTY
186              
187             Absolutely, positively NO WARRANTY, neither express or implied, is
188             offered with this software. You use this software at your own risk. In
189             case of loss, no person or entity owes you anything whatsoever. You
190             have been warned.
191              
192             =head1 LICENSE
193              
194             This program is free software; you can redistribute it and/or modify it
195             under the same terms as Perl itself.
196              
197             =cut
198              
199             # vi:ts=2:sw=2:et:sta
200             1;