File Coverage

blib/lib/Object/Factory/Declarative.pm
Criterion Covered Total %
statement 94 137 68.6
branch 21 52 40.3
condition 4 13 30.7
subroutine 16 23 69.5
pod 0 5 0.0
total 135 230 58.7


line stmt bran cond sub pod time code
1             package Object::Factory::Declarative;
2            
3 1     1   16955 use 5.006;
  1         5  
  1         44  
4 1     1   7 use strict;
  1         2  
  1         51  
5 1     1   7 use warnings;
  1         6  
  1         36  
6 1     1   6 use Carp;
  1         2  
  1         449  
7            
8             our @ISA = qw();
9            
10             our $VERSION = '0.07';
11            
12             my @decl_keys = qw(constructor constructor_args method method_args package);
13            
14             sub expand_scalar_arg
15             {
16 3     3 0 6 my ($obj, $name, $arg) = @_;
17 3         4 my @res = ($arg);
18 3 50       9 if(@_>3)
19             {
20 3         4 my $opt = $_[3];
21 1     1   8 eval { no warnings; @res = $obj->$arg($opt, $name); };
  1         2  
  1         60  
  3         4  
  3         12  
22             }
23             else
24             {
25 1     1   5 eval { no warnings; @res = $obj->$arg($name); };
  1         1  
  1         417  
  0         0  
  0         0  
26             }
27 3 50       21 wantarray?@res:pop @res;
28             }
29            
30             sub expand_array_arg
31             {
32 0     0 0 0 my ($obj, $name, @args) = @_;
33 0         0 my @res;
34 0         0 push @res, expand_scalar_arg($obj, $name, $_) foreach @args;
35 0 0       0 wantarray?@res:pop @res;
36             }
37            
38             sub expand_hash_arg
39             {
40 2     2 0 11 my ($obj, $name, @args) = @_;
41 2 50       7 return expand_array_arg($obj, $name, @args) if @args&1;
42 2         3 my @res;
43 2         5 my %args = @args;
44             push @res, $_, expand_scalar_arg($obj, $name, $args{$_}, $_)
45 2         11 foreach keys %args;
46 2 50       15 wantarray?@res:pop @res;
47             }
48            
49             sub expand_credentials
50             {
51 2     2 0 4 my ($argf) = @_;
52 2 50   0   5 return sub {} unless defined $argf;
  0         0  
53 2 50       5 return (\&expand_scalar_arg, $argf) unless ref $argf;
54 2         4 my @res = ($argf);
55 1     1   6 eval { no warnings; @res = @$argf; };
  1         2  
  1         69  
  2         2  
  2         16  
56 2 50       5 return (\&expand_array_arg, @res) unless $@;
57 1     1   6 eval { no warnings; @res = %$argf; };
  1         2  
  1         197  
  2         3  
  2         6  
58 2 50       16 return (\&expand_hash_arg, @res) unless $@;
59 0         0 return (\&expand_scalar_arg, @res);
60             }
61            
62             sub generate_method
63             {
64 1     1 0 3 my ($class, $name, $cons, $c_args, $init, $i_args) = @_;
65 1   33     6 my $package = ref $class || $class;
66 1         3 my $fullname = $package . '::' . $name;
67 1         3 my ($cons_expand_func, @c_args) = expand_credentials($c_args);
68 1         2 my ($init_expand_func, @i_args) = expand_credentials($i_args);
69 1     1   6 no strict 'refs';
  1         2  
  1         745  
70             # We have several similar cases...
71             # Case 1a & 1b - no init method
72 1 50       4 unless($init)
73             {
74             # 1a - with constructor args
75 0 0       0 if(@c_args)
76             {
77             *$fullname = sub
78             {
79 0     0   0 my ($obj) = @_;
80 0         0 $obj->$cons(&{$cons_expand_func}($obj, $name, @c_args));
  0         0  
81 0         0 } ;
82             }
83             # 2a - without constructor args
84             else
85             {
86             *$fullname = sub
87             {
88 0     0   0 my ($obj) = @_;
89 0         0 $obj->$cons;
90 0         0 } ;
91             }
92 0         0 return;
93             }
94             # Case 2a & 2b - init method, no init args
95 1 50       2 unless(@i_args)
96             {
97             # 2a - with constructor args
98 0 0       0 if(@c_args)
99             {
100             *$fullname = sub
101             {
102 0     0   0 my ($obj, @args) = @_;
103 0         0 my $rv = $obj->$cons(&{$cons_expand_func}($obj,
  0         0  
104             $name, @c_args));
105 0         0 $rv->$init;
106             # expand_hash_arg will convert to expand_array_arg...
107 0 0       0 $rv->$init(expand_hash_arg($obj, $name, @args)) if @args;
108 0         0 $rv;
109 0         0 } ;
110             }
111             # 2b - without constructor args
112             else
113             {
114             *$fullname = sub
115             {
116 0     0   0 my ($obj, @args) = @_;
117 0         0 my $rv = $obj->$cons;
118 0         0 $rv->$init;
119             # expand_hash_arg will convert to expand_array_arg...
120 0 0       0 $rv->$init(expand_hash_arg($rv, $name, @args)) if @args;
121 0         0 $rv;
122 0         0 } ;
123             }
124 0         0 return;
125             }
126             # Case 3a & 3b - init with args
127             # 3a - with constructor args
128 1 50       4 if(@c_args)
129             {
130             *$fullname = sub
131             {
132 1     1   90 my ($obj, @args) = @_;
133 1         3 my $rv = $obj->$cons(&{$cons_expand_func}($obj,
  1         6  
134             $name, @c_args));
135 1         18 $rv->$init(&{$init_expand_func}($obj, $name, @i_args));
  1         4  
136 1 50       26 $rv->$init(&{$init_expand_func}($obj, $name, @args)) if @args;
  0         0  
137 1         3 $rv;
138 1         2372 } ;
139             }
140             # 3b - without constructor args
141             else
142             {
143             *$fullname = sub
144             {
145 0     0   0 my ($obj, @args) = @_;
146 0         0 my $rv = $obj->$cons;
147 0         0 $rv->$init(&{$init_expand_func}($obj, $name, @i_args));
  0         0  
148 0 0       0 $rv->$init(&{$init_expand_func}($obj, $name, @args)) if @args;
  0         0  
149 0         0 $rv;
150 0         0 } ;
151             }
152             }
153            
154             sub import
155             {
156 2     2   29 my ($package, @args) = @_;
157 2 50 0     8 carp "Expected an even number of arguments" and return if @args&1;
158 2         6 my $callpkg = caller;
159 2         5 my %defaults =
160             (
161             package => $callpkg,
162             ) ;
163 2         128 while(@args)
164             {
165 2         11 my ($name, $ref) = splice @args, 0, 2;
166 2         3 my %h;
167 2 100       14 if('--defaults' eq $name)
168             {
169 1         3 %defaults = ( package => $callpkg );
170 1         4 %h = %$ref;
171 1         3 foreach my $k (grep { exists $h{$_}; } @decl_keys)
  5         11  
172             {
173 4         6 delete $defaults{$k};
174 4         6 my $v = delete $h{$k};
175 4 50       15 $defaults{$k} = $v if defined $v;
176             }
177 1 50       4 carp "Unexpected declaration key(s) ", join(',', keys %h) if %h;
178 1         4 next;
179             }
180 1 50       4 if('--export-to' eq $name)
181             {
182 1     1   8 no strict 'refs';
  1         3  
  1         229  
183 0         0 *$ref = \&generate_method;
184 0         0 next;
185             }
186 1         3 %h = %$ref;
187 1         2 my %p;
188 1   66     20 $p{$_} = delete $h{$_} || $defaults{$_} foreach @decl_keys;
189 1 50       5 carp "Unexpected declaration key(s) ", join(',', keys %h) if %h;
190 1 50 33     9 carp "Can't have initialization args without an initialization method"
191             if $p{method_args} and not $p{method};
192 1 50 0     4 carp "Missing constructor" and next unless $p{constructor};
193 1         12 generate_method($p{package}, $name, @p{qw(constructor constructor_args
194             method method_args)});
195             }
196             }
197            
198             1;
199             __END__