File Coverage

blib/lib/Class/Property.pm
Criterion Covered Total %
statement 41 49 83.6
branch 2 2 100.0
condition n/a
subroutine 17 21 80.9
pod 0 4 0.0
total 60 76 78.9


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