File Coverage

blib/lib/Connector/Builtin/Memory.pm
Criterion Covered Total %
statement 105 114 92.1
branch 40 54 74.0
condition 2 6 33.3
subroutine 16 16 100.0
pod 8 8 100.0
total 171 198 86.3


line stmt bran cond sub pod time code
1             # Connector::Builtin::Memory
2             #
3             # Proxy class for reading YAML configuration
4             #
5             # Written by Scott Hardin, Martin Bartosch and Oliver Welter
6             # for the OpenXPKI project 2012
7             #
8             # THIS IS NOT WORKING IN A FORKING ENVIRONMENT!
9              
10              
11             package Connector::Builtin::Memory;
12              
13 9     9   311381 use strict;
  9         34  
  9         250  
14 9     9   43 use warnings;
  9         16  
  9         206  
15 9     9   45 use English;
  9         16  
  9         69  
16 9     9   3849 use Data::Dumper;
  9         5925  
  9         423  
17              
18 9     9   982 use Moose;
  9         790925  
  9         54  
19             extends 'Connector::Builtin';
20              
21             has '+LOCATION' => ( required => 0 );
22              
23             has 'primary_attribute' => (
24             is => 'ro',
25             isa => 'Str',
26             predicate => 'has_primary_attribute',
27             );
28              
29             sub _build_config {
30 3     3   6 my $self = shift;
31 3         66 $self->_config( {} );
32             }
33              
34             sub _get_node {
35              
36 321     321   414 my $self = shift;
37 321         706 my @path = $self->_build_path_with_prefix( shift );
38              
39 321         6684 $self->log()->trace('get node for path'. Dumper \@path);
40              
41 321         19667 my $ptr = $self->_config();
42              
43             # Top Level Node requested
44 321 100       711 if (!@path) {
45 12         33 return $ptr;
46             }
47              
48 309         636 while ( scalar @path > 1 ) {
49 528         726 my $entry = shift @path;
50 528 100       1061 if ( exists $ptr->{$entry} ) {
51 524 100       945 if ( ref $ptr->{$entry} eq 'HASH' ) {
52 520         1038 $ptr = $ptr->{$entry};
53             }
54             else {
55 4         12 return $self->_node_not_exists( ref $ptr->{$entry} );
56             }
57             } else {
58 4         29 return $self->_node_not_exists($entry);
59             }
60             }
61              
62 301         794 return $ptr->{ shift @path };
63              
64             }
65              
66             sub get {
67              
68 69     69 1 5108 my $self = shift;
69 69         197 my $value = $self->_get_node( shift );
70              
71 69 100       210 return $self->_node_not_exists() unless (defined $value);
72              
73 63 100       138 if (ref $value ne '') {
74 1 50 33     32 die "requested value is not a scalar"
75             unless ($self->has_primary_attribute() && ref $value eq 'HASH');
76              
77             return $self->_node_not_exists()
78 1 50       25 unless (defined $value->{$self->primary_attribute});
79              
80             die "primary_attribute is not a scalar"
81 1 50       24 unless (ref $value->{$self->primary_attribute} eq '');
82              
83 1         23 return $value->{$self->primary_attribute};
84             }
85              
86 62         415 return $value;
87              
88             }
89              
90             sub get_size {
91              
92 2     2 1 15 my $self = shift;
93 2         6 my $node = $self->_get_node( shift );
94              
95 2 50       11 return 0 unless(defined $node);
96              
97 2 50       7 if ( ref $node ne 'ARRAY' ) {
98 0         0 die "requested value is not a list"
99             }
100              
101 2         4 return scalar @{$node};
  2         8  
102             }
103              
104             sub get_list {
105              
106 6     6 1 16 my $self = shift;
107 6         19 my $path = shift;
108              
109 6         18 my $node = $self->_get_node( $path );
110              
111 6 100       43 return $self->_node_not_exists( $path ) unless(defined $node);
112              
113 5 50       19 if ( ref $node ne 'ARRAY' ) {
114 0         0 die "requested value is not a list"
115             }
116              
117 5         7 return @{$node};
  5         33  
118             }
119              
120             sub get_keys {
121              
122 14     14 1 38 my $self = shift;
123 14         22 my $path = shift;
124              
125 14         52 my $node = $self->_get_node( $path );
126              
127 14 50       51 return @{[]} unless(defined $node);
  0         0  
128              
129 14 50       43 if ( ref $node ne 'HASH' ) {
130 0         0 die "requested value is not a hash"
131             }
132              
133 14         22 return keys %{$node};
  14         107  
134             }
135              
136             sub get_hash {
137              
138 6     6 1 1287 my $self = shift;
139 6         9 my $path = shift;
140              
141 6         14 my $node = $self->_get_node( $path );
142              
143 6 100       22 return $self->_node_not_exists( $path ) unless(defined $node);
144              
145 5 50       16 if ( ref $node ne 'HASH' ) {
146 0         0 die "requested value is not a hash"
147             }
148              
149 5         36 return { %$node };
150             }
151              
152             sub get_meta {
153              
154 203     203 1 286 my $self = shift;
155              
156 203         366 my $node = $self->_get_node( shift );
157              
158 203         3655 $self->log()->trace('get_node returned '. Dumper $node);
159              
160 203 100       8719 if (!defined $node) {
161             # die_on_undef already handled by get_node
162 100         320 return;
163             }
164              
165 103         175 my $meta = {};
166              
167 103 100 33     361 if (ref $node eq '') {
    100          
    100          
    100          
    50          
168 36         101 $meta = {TYPE => "scalar", VALUE => $node };
169             } elsif (ref $node eq "SCALAR") {
170 23         85 $meta = {TYPE => "reference", VALUE => $$node };
171             } elsif (ref $node eq "ARRAY") {
172 5         20 $meta = {TYPE => "list", VALUE => $node };
173             } elsif (ref $node eq "HASH") {
174 36         46 my @keys = keys(%{$node});
  36         94  
175 36         155 $meta = {TYPE => "hash", VALUE => \@keys };
176             } elsif (blessed($node) && $node->isa('Connector')) {
177 3         13 $meta = {TYPE => "connector", VALUE => $node };
178             } else {
179 0         0 die "Unsupported node type: " . ref $node;
180             }
181 103         282 return $meta;
182             }
183              
184             sub exists {
185              
186 21     21 1 540 my $self = shift;
187              
188 21         33 my $value = 0;
189 21         31 eval {
190 21         60 $value = defined $self->_get_node( shift );
191             };
192 21         151 return $value;
193              
194             }
195              
196             sub set {
197              
198 9     9 1 43 my $self = shift;
199 9         30 my @path = $self->_build_path_with_prefix( shift );
200              
201 9         16 my $value = shift;
202              
203 9         225 my $ptr = $self->_config();
204              
205 9         21 while (scalar @path > 1) {
206 5         8 my $entry = shift @path;
207 5 100       16 if (!exists $ptr->{$entry}) {
    50          
208 4         18 $ptr->{$entry} = {};
209             } elsif (ref $ptr->{$entry} ne "HASH") {
210 0         0 confess('Try to step over a value node at ' . $entry);
211             }
212 5         13 $ptr = $ptr->{$entry};
213             }
214              
215 9         17 my $entry = shift @path;
216              
217 9 100       16 if (!defined $value) {
218 1         3 delete $ptr->{$entry};
219 1         4 return;
220             }
221              
222 8 50       16 if (exists $ptr->{$entry}) {
223 0 0       0 if (ref $ptr->{$entry} ne ref $value) {
224 0         0 confess('Try to override data type at node ' . $entry);
225             }
226             }
227 8         18 $ptr->{$entry} = $value;
228 8         18 return 1;
229             }
230              
231              
232 9     9   60473 no Moose;
  9         21  
  9         49  
233             __PACKAGE__->meta->make_immutable;
234              
235             1;
236             __END__
237              
238             =head1 Name
239              
240             Connector::Builtin::Memory
241              
242             =head1 Description
243              
244             A connector implementation to allow memory based caching
245              
246             =head1 Parameters
247              
248             =over
249              
250             =item LOCATION
251              
252             Not used
253              
254             =item primary_attribute
255              
256             If your data consists of hashes as leaf nodes, set this to the name of
257             the node that is considered the primary attribute, e.g. the name of a
258             person. If you now access the key on the penultimate level using I<get>
259             you will receive the value of this attribute back.
260              
261             user1234:
262             name: John Doe
263             email: john.doe@acme.com
264              
265             When you call I<get(user1234)> on this structure, the connector will
266             usually die with a "not a scalar" error. With I<primary_attribute = name>
267             you will get back I<John Doe>.
268              
269             =back