File Coverage

blib/lib/Exodist/Util/Accessors.pm
Criterion Covered Total %
statement 142 148 95.9
branch 13 22 59.0
condition 6 7 85.7
subroutine 38 40 95.0
pod 0 4 0.0
total 199 221 90.0


line stmt bran cond sub pod time code
1             package Exodist::Util::Accessors;
2 3     3   54832 use strict;
  3         7  
  3         116  
3 3     3   16 use warnings;
  3         6  
  3         82  
4              
5 3     3   45 use Exporter::Declare;
  3         11  
  3         17  
6 3     3   4982 use Exodist::Util::Package qw/inject_sub/;
  3         8  
  3         19  
7 3     3   642 use Scalar::Util qw/blessed/;
  3         5  
  3         161  
8 3     3   16 use Carp qw/croak/;
  3         13  
  3         5549  
9              
10             default_exports qw/
11             abstract
12             accessors
13             array_accessors
14             category_accessors
15             /;
16              
17             sub abstract {
18 0     0 0 0 my $caller = caller;
19              
20 0         0 for my $name ( @_ ) {
21 0     0   0 inject_sub( $caller, $name, sub { croak "$caller does not implement $name()" });
  0         0  
22             }
23             }
24              
25             sub accessors {
26 1     1 0 642 my $caller = caller;
27 1         3 for my $accessor (@_) {
28 4 100       14 my ( $name, $default ) = ref( $accessor ) ? @$accessor : ( $accessor );
29 4         13 inject_sub( $caller, $name, _simple_accessor( $name, $default ))
30             }
31             }
32              
33             sub array_accessors {
34 1     1 0 244 my $caller = caller;
35 1         5 _array_subs( $caller, $_ ) for @_;
36             }
37              
38             sub category_accessors {
39 1     1 0 3 my $caller = caller;
40 1         7 _category_subs( $caller, $_ ) for @_;
41             }
42              
43             sub _simple_accessor {
44 8     8   16 my ( $name, $default ) = @_;
45             return sub {
46 46     46   1748 my $self = shift;
47 46         90 _verify_self( $self );
48 46 100       129 ( $self->{$name} ) = @_ if @_;
49 46 100 100     215 $self->{$name} = $default->()
50             if $default && !exists $self->{$name};
51 46         176 return $self->{$name};
52 8         57 };
53             }
54              
55             sub _array_subs {
56 2     2   4 my ( $package, $name ) = @_;
57 2         5 my $refname = join( '_', $name, 'ref' );
58 2         5 my $pullname = join( '_', 'pull', $name );
59 2         4 my $pushname = join( '_', 'push', $name );
60 2         5 my $popname = join( '_', 'pop', $name );
61 2         4 my $unshiftname = join( '_', 'unshift', $name );
62 2         4 my $shiftname = join( '_', 'shift', $name );
63              
64 2     2   9 inject_sub( $package, $refname, _simple_accessor( $refname, sub {[]} ));
  2         7  
65 2         7 inject_sub( $package, $name, _arr_all_accessor( $refname, ));
66 2         6 inject_sub( $package, $pushname, _arr_push_accessor( $refname, ));
67 2         7 inject_sub( $package, $pullname, _arr_pull_accessor( $refname, ));
68 2         5 inject_sub( $package, $popname, _arr_pop_accessor( $refname, ));
69 2         6 inject_sub( $package, $unshiftname, _arr_unshift_accessor( $refname, ));
70 2         7 inject_sub( $package, $shiftname, _arr_shift_accessor( $refname, ));
71             }
72              
73             sub _category_subs {
74 2     2   4 my ( $package, $name ) = @_;
75 2         6 my $refname = join( '_', $name, 'ref' );
76 2         5 my $pullname = join( '_', 'pull', $name );
77 2         4 my $pushname = join( '_', 'push', $name );
78 2         4 my $keysname = join( '_', 'keys', $name );
79 2         6 my $pullallname = join( '_', 'pull_all', $name );
80              
81 2     1   24 inject_sub( $package, $refname, _simple_accessor( $refname, sub {{}} ));
  1         3  
82 2         6 inject_sub( $package, $name, _cat_all_accessor( $refname ));
83 2         7 inject_sub( $package, $pullname, _cat_pull_accessor( $refname ));
84 2         7 inject_sub( $package, $pushname, _cat_push_accessor( $refname ));
85 2         7 inject_sub( $package, $keysname, _cat_keys_accessor( $refname ));
86 2         6 inject_sub( $package, $pullallname, _cat_pull_all_accessor( $refname ));
87             }
88              
89             sub _cat_pull_accessor {
90 2     2   5 my ( $refname ) = @_;
91             return sub {
92 1     1   3 my $self = shift;
93 1         4 _verify_self( $self );
94 1         2 my ( $type ) = @_;
95 1   50     4 $type ||= '!';
96 1         4 my $ref = $self->$refname;
97 1 50       40 return @{ delete $ref->{ $type } || [] };
  1         12  
98 2         21 };
99             }
100              
101             sub _cat_push_accessor {
102 2     2   6 my ( $refname ) = @_;
103             return sub {
104 2     2   4 my $self = shift;
105 2         8 _verify_self( $self );
106 2 50       7 return unless @_;
107 2         7 my $ref = $self->$refname;
108 3   100     25 push @{ $ref->{ blessed($_) || '!' }} => $_
109 2         5 for @_;
110 2         12 };
111             }
112              
113             sub _cat_keys_accessor {
114 2     2   5 my ( $refname ) = @_;
115             return sub {
116 2     2   5 my $self = shift;
117 2         16 _verify_self( $self );
118 2         7 my $ref = $self->$refname;
119 2         19 return keys %$ref;
120 2         19 };
121             }
122              
123             sub _cat_all_accessor {
124 2     2   4 my ( $refname ) = @_;
125             return sub {
126 5     5   10 my $self = shift;
127 5         849 _verify_self( $self );
128 5         7 my ( $type ) = @_;
129 5         16 my $ref = $self->$refname;
130 5 0       12 return @{ $ref->{ $type } || [] } if $type;
  0 50       0  
131 5 50       22 return( map { @$_ ? (@$_) : () } values %$ref );
  5         43  
132 2         14 };
133             }
134              
135             sub _cat_pull_all_accessor {
136 2     2   5 my ( $refname ) = @_;
137             return sub {
138 1     1   4 my $self = shift;
139 1         4 _verify_self( $self );
140 1         4 my $ref = $self->$refname;
141 1 50       4 my @out = map { @$_ ? (@$_) : () } values %$ref;
  2         21  
142 1         7 $self->$refname({});
143 1         12 return @out;
144 2         13 };
145             }
146              
147             sub _arr_all_accessor {
148 2     2   5 my ( $refname ) = @_;
149             return sub {
150 4     4   8 my $self = shift;
151 4         10 _verify_self( $self );
152 4         12 my $ref = $self->$refname;
153 4         21 return @$ref;
154 2         12 };
155             }
156              
157             sub _arr_push_accessor {
158 2     2   4 my ( $refname ) = @_;
159             return sub {
160 1     1   2 my $self = shift;
161 1         4 _verify_self( $self );
162 1 50       4 return unless @_;
163 1         5 my $ref = $self->$refname;
164 1         5 push @$ref => @_;
165 2         10 };
166             }
167              
168             sub _arr_pull_accessor {
169 2     2   4 my ( $refname ) = @_;
170             return sub {
171 1     1   3 my $self = shift;
172 1         5 _verify_self( $self );
173 1         4 my $ref = $self->$refname;
174 1         4 $self->$refname([]);
175 1         8 return @$ref;
176 2         11 };
177             }
178              
179             sub _arr_pop_accessor {
180 2     2   4 my ( $refname ) = @_;
181             return sub {
182 1     1   2 my $self = shift;
183 1         4 _verify_self( $self );
184 1         4 my $ref = $self->$refname;
185 1         5 pop @$ref;
186 2         12 };
187             }
188              
189             sub _arr_unshift_accessor {
190 2     2   4 my ( $refname ) = @_;
191             return sub {
192 1     1   2 my $self = shift;
193 1         4 _verify_self( $self );
194 1         4 my $ref = $self->$refname;
195 1         4 unshift @$ref => @_;
196 2         9 };
197             }
198              
199             sub _arr_shift_accessor {
200 2     2   3 my ( $refname ) = @_;
201             return sub {
202 1     1   3 my $self = shift;
203 1         3 _verify_self( $self );
204 1         4 my $ref = $self->$refname;
205 1         5 shift @$ref;
206 2         26 };
207             }
208              
209             sub _verify_self {
210 66     66   91 my ( $self ) = @_;
211 66 50       295 return if blessed( $self );
212 0           croak "Attempted to use accessor on unblessed item '$self'";
213             }
214              
215             1;
216              
217             __END__