File Coverage

blib/lib/Class/Property.pm
Criterion Covered Total %
statement 40 48 83.3
branch 2 2 100.0
condition n/a
subroutine 17 21 80.9
pod 0 4 0.0
total 59 75 78.6


line stmt bran cond sub pod time code
1             package Class::Property;
2 1     1   16265 use strict; use warnings FATAL => 'all';
  1     1   2  
  1         41  
  1         4  
  1         1  
  1         50  
3 1     1   439 use parent 'Exporter';
  1         259  
  1         5  
4 1     1   119 use 5.016;
  1         3  
  1         27  
5 1     1   6 use Carp;
  1         2  
  1         989  
6            
7             our $VERSION = 'v1.0.1';
8            
9             our @EXPORT;
10            
11             my $GEN = {
12             'default' => sub
13             {
14             my( $prop_name ) = @_;
15            
16             return sub: lvalue
17             {
18 9     9   630 return shift->{$prop_name};
19             };
20             },
21             'default_lazy' => sub
22             {
23             my( $prop_name, $lazy_init ) = @_;
24             require Class::Property::RW::Lazy;
25             my $lazy_called = 0;
26             my $dummy;
27             my $wrapper = tie $dummy, 'Class::Property::RW::Lazy', $prop_name, $lazy_init, \$lazy_called;
28            
29             return sub: lvalue
30             {
31 8 100   8   423 if( $lazy_called )
32             {
33 5         27 return shift->{$prop_name};
34             }
35             else
36             {
37 3         19 $wrapper->set_object(shift);
38 3         19 return $dummy;
39             }
40             };
41             },
42             'lazy_get_default_set' => sub
43             {
44             my( $prop_name, $lazy_init, $setter ) = @_;
45             require Class::Property::RW::Lazy::CustomSet;
46             my $lazy_called = 0;
47             my $dummy;
48             my $wrapper = tie $dummy, 'Class::Property::RW::Lazy::CustomSet', $prop_name, $lazy_init, $setter, \$lazy_called;
49            
50             return sub: lvalue
51             {
52 0     0   0 $wrapper->set_object(shift);
53 0         0 return $dummy;
54             };
55             },
56             'custom' => sub
57             {
58             my( $getter, $setter ) = @_;
59             require Class::Property::RW::Custom;
60             my $dummy;
61             my $wrapper = tie $dummy, 'Class::Property::RW::Custom', $getter, $setter;
62            
63             return sub: lvalue
64             {
65 2     2   838 $wrapper->set_object(shift);
66 2         13 return $dummy;
67             };
68             },
69             'default_get_custom_set' => sub
70             {
71             my( $prop_name, $setter ) = @_;
72             require Class::Property::RW::CustomSet;
73             my $dummy;
74             my $wrapper = tie $dummy, 'Class::Property::RW::CustomSet', $prop_name, $setter;
75            
76             return sub: lvalue
77             {
78 0     0   0 $wrapper->set_object(shift);
79 0         0 return $dummy;
80             };
81             },
82             'custom_get_default_set' => sub
83             {
84             my( $prop_name, $getter ) = @_;
85             require Class::Property::RW::CustomGet;
86             my $dummy;
87             my $wrapper = tie $dummy, 'Class::Property::RW::CustomGet', $prop_name, $getter;
88            
89             return sub: lvalue
90             {
91 3     3   22 $wrapper->set_object(shift);
92 3         24 return $dummy;
93             };
94             },
95             'default_ro' => sub
96             {
97             my( $prop_name ) = @_;
98             require Class::Property::RO;
99             my $dummy;
100             my $wrapper = tie $dummy, 'Class::Property::RO', $prop_name;
101            
102             return sub: lvalue
103             {
104 7     7   45 $wrapper->set_object(shift);
105 7         35 return $dummy;
106             };
107             },
108             'custom_ro' => sub
109             {
110             my( $prop_name, $getter ) = @_;
111             require Class::Property::RO::CustomGet;
112             my $dummy;
113             my $wrapper = tie $dummy, 'Class::Property::RO::CustomGet', $prop_name, $getter;
114            
115             return sub: lvalue
116             {
117 0     0   0 $wrapper->set_object(shift);
118 0         0 return $dummy;
119             };
120             },
121             'lazy_ro' => sub
122             {
123             my( $prop_name, $lazy_init ) = @_;
124             require Class::Property::RO::Lazy;
125             my $lazy_called = 0;
126             my $dummy;
127             my $wrapper = tie $dummy, 'Class::Property::RO::Lazy', $prop_name, $lazy_init, \$lazy_called;
128            
129             return sub: lvalue
130             {
131 3     3   325 $wrapper->set_object(shift);
132 3         24 return $dummy;
133             };
134             },
135             'default_wo' => sub: lvalue
136             {
137             my( $prop_name ) = @_;
138             require Class::Property::WO;
139             my $dummy;
140             my $wrapper = tie $dummy, 'Class::Property::WO', $prop_name;
141            
142             return sub: lvalue
143             {
144 5     5   1632 $wrapper->set_object(shift);
145 5         35 return $dummy;
146             };
147             },
148             'custom_wo' => sub: lvalue
149             {
150             my( $prop_name, $setter ) = @_;
151             require Class::Property::WO::CustomSet;
152             my $dummy;
153             my $wrapper = tie $dummy, 'Class::Property::WO::CustomSet', $prop_name, $setter;
154            
155             return sub: lvalue
156             {
157 0     0   0 $wrapper->set_object(shift);
158 0         0 return $dummy;
159             };
160             },
161             };
162            
163             # creating new property by names
164             # input is a hash of
165             # property_name => hashref
166             # and hashref is:
167             #
168             # get => CODEREF | anything # creates getter custom or default
169             # get_lazy => CODEREF # creates default getter with lazy init method from CODEREF
170             # set => CODREF | anything # creates custom or default setter
171             #
172             my $make_property = sub
173             {
174             my( $package, %kwargs ) = @_;
175            
176             #use Data::Dumper; warn "Invoked $package with ".Dumper(\%kwargs);
177            
178             foreach my $prop_name (keys(%kwargs))
179             {
180             my $prop_settings = $kwargs{$prop_name};
181             my $prop_methodname = "${package}::$prop_name";
182             my $prop_method;
183            
184             if( # regular property
185             exists $prop_settings->{'get'}
186             and exists $prop_settings->{'set'}
187             )
188             {
189             my( $get_type, $set_type ) = ( ref $prop_settings->{'get'}, ref $prop_settings->{'set'} );
190            
191             if( $get_type eq 'CODE' and $set_type eq 'CODE' ) # custom setter and gettter
192             {
193             $prop_method = $GEN->{'custom'}->(@{$prop_settings}{'get', 'set'});
194             }
195             elsif( $get_type eq 'CODE' ) # custom getter and default setter
196             {
197             $prop_method = $GEN->{'custom_get_default_set'}->($prop_name, @{$prop_settings}{'get'});
198             }
199             elsif( $set_type eq 'CODE' ) # default getter and custom setter
200             {
201             $prop_method = $GEN->{'default_get_custom_set'}->($prop_name, @{$prop_settings}{'set'});
202             }
203             else # default getter and setter
204             {
205             $prop_method = $GEN->{'default'}->($prop_name);
206             }
207             }
208             elsif( # regular property with lazy init
209             exists $prop_settings->{'get_lazy'}
210             and exists $prop_settings->{'set'}
211             )
212             {
213             croak 'get_lazy parameter should be a coderef' if ref $prop_settings->{'get_lazy'} ne 'CODE';
214             my $set_type = ref $prop_settings->{'set'};
215             if( $set_type eq 'CODE' )
216             {
217             $prop_method = $GEN->{'lazy_get_default_set'}->($prop_name, $prop_settings->{'get_lazy'}, $prop_settings->{'set'});
218             }
219             else
220             {
221             $prop_method = $GEN->{'default_lazy'}->($prop_name, $prop_settings->{'get_lazy'});
222             }
223             }
224             elsif( exists $prop_settings->{'get'} ) # ro property
225             {
226             if( ref $prop_settings->{'get'} eq 'CODE' ) # RO custom getter
227             {
228             $prop_method = $GEN->{'custom_ro'}->($prop_name, $prop_settings->{'get'});
229             }
230             else
231             {
232             $prop_method = $GEN->{'default_ro'}->($prop_name);
233             }
234             }
235             elsif( exists $prop_settings->{'get_lazy'} ) # ro property with lazy init
236             {
237             croak 'get_lazy parameter should be a coderef' if ref $prop_settings->{'get_lazy'} ne 'CODE';
238             $prop_method = $GEN->{'lazy_ro'}->($prop_name, $prop_settings->{'get_lazy'});
239             }
240             elsif( exists $prop_settings->{'set'} ) # wo property
241             {
242             if( ref $prop_settings->{'set'} eq 'CODE' ) # WO custom setter
243             {
244             $prop_method = $GEN->{'custom_wo'}->($prop_name, $prop_settings->{'set'});
245             }
246             else
247             {
248             $prop_method = $GEN->{'default_wo'}->($prop_name);
249             }
250             }
251            
252             if(defined $prop_method)
253             {
254 1     1   5 no strict 'refs';
  1         1  
  1         275  
255             *{$prop_methodname} = $prop_method;
256             }
257             }
258            
259             return $package;
260             };
261            
262             push @EXPORT, 'property';
263 2     2 0 4088 sub property{ return $make_property->( (caller)[0], @_);}
264             push @EXPORT, 'rw_property';
265 1     1 0 10 sub rw_property{ return $make_property->( (caller)[0], map{$_ => {'set' => undef, 'get' => undef }} @_);}
  2         8  
266             push @EXPORT, 'ro_property';
267 1     1 0 6 sub ro_property{ return $make_property->( (caller)[0], map{$_ => {'get' => undef }} @_);}
  1         4  
268             push @EXPORT, 'wo_property';
269 1     1 0 7 sub wo_property{ return $make_property->( (caller)[0], map{$_ => {'set' => undef }} @_);}
  1         4  
270            
271             __END__