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   368592 use strict;
  9         39  
  9         282  
14 9     9   51 use warnings;
  9         28  
  9         226  
15 9     9   52 use English;
  9         26  
  9         76  
16 9     9   4527 use Data::Dumper;
  9         7113  
  9         471  
17              
18 9     9   1252 use Moose;
  9         948021  
  9         59  
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   8 my $self = shift;
31 3         85 $self->_config( {} );
32             }
33              
34             sub _get_node {
35              
36 321     321   498 my $self = shift;
37 321         896 my @path = $self->_build_path_with_prefix( shift );
38              
39 321         8679 $self->log()->trace('get node for path'. Dumper \@path);
40              
41 321         24620 my $ptr = $self->_config();
42              
43             # Top Level Node requested
44 321 100       832 if (!@path) {
45 12         38 return $ptr;
46             }
47              
48 309         773 while ( scalar @path > 1 ) {
49 528         919 my $entry = shift @path;
50 528 100       1207 if ( exists $ptr->{$entry} ) {
51 524 100       1190 if ( ref $ptr->{$entry} eq 'HASH' ) {
52 520         1249 $ptr = $ptr->{$entry};
53             }
54             else {
55 4         13 return $self->_node_not_exists( ref $ptr->{$entry} );
56             }
57             } else {
58 4         33 return $self->_node_not_exists($entry);
59             }
60             }
61              
62 301         987 return $ptr->{ shift @path };
63              
64             }
65              
66             sub get {
67              
68 69     69 1 5911 my $self = shift;
69 69         223 my $value = $self->_get_node( shift );
70              
71 69 100       238 return $self->_node_not_exists() unless (defined $value);
72              
73 63 100       185 if (ref $value ne '') {
74 1 50 33     45 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       35 unless (defined $value->{$self->primary_attribute});
79              
80             die "primary_attribute is not a scalar"
81 1 50       30 unless (ref $value->{$self->primary_attribute} eq '');
82              
83 1         28 return $value->{$self->primary_attribute};
84             }
85              
86 62         524 return $value;
87              
88             }
89              
90             sub get_size {
91              
92 2     2 1 19 my $self = shift;
93 2         6 my $node = $self->_get_node( shift );
94              
95 2 50       9 return 0 unless(defined $node);
96              
97 2 50       10 if ( ref $node ne 'ARRAY' ) {
98 0         0 die "requested value is not a list"
99             }
100              
101 2         5 return scalar @{$node};
  2         11  
102             }
103              
104             sub get_list {
105              
106 6     6 1 16 my $self = shift;
107 6         14 my $path = shift;
108              
109 6         21 my $node = $self->_get_node( $path );
110              
111 6 100       51 return $self->_node_not_exists( $path ) unless(defined $node);
112              
113 5 50       26 if ( ref $node ne 'ARRAY' ) {
114 0         0 die "requested value is not a list"
115             }
116              
117 5         9 return @{$node};
  5         45  
118             }
119              
120             sub get_keys {
121              
122 14     14 1 38 my $self = shift;
123 14         29 my $path = shift;
124              
125 14         48 my $node = $self->_get_node( $path );
126              
127 14 50       51 return @{[]} unless(defined $node);
  0         0  
128              
129 14 50       56 if ( ref $node ne 'HASH' ) {
130 0         0 die "requested value is not a hash"
131             }
132              
133 14         26 return keys %{$node};
  14         139  
134             }
135              
136             sub get_hash {
137              
138 6     6 1 1914 my $self = shift;
139 6         13 my $path = shift;
140              
141 6         19 my $node = $self->_get_node( $path );
142              
143 6 100       24 return $self->_node_not_exists( $path ) unless(defined $node);
144              
145 5 50       18 if ( ref $node ne 'HASH' ) {
146 0         0 die "requested value is not a hash"
147             }
148              
149 5         43 return { %$node };
150             }
151              
152             sub get_meta {
153              
154 203     203 1 341 my $self = shift;
155              
156 203         460 my $node = $self->_get_node( shift );
157              
158 203         4600 $self->log()->trace('get_node returned '. Dumper $node);
159              
160 203 100       10617 if (!defined $node) {
161             # die_on_undef already handled by get_node
162 100         367 return;
163             }
164              
165 103         205 my $meta = {};
166              
167 103 100 33     445 if (ref $node eq '') {
    100          
    100          
    100          
    50          
168 36         144 $meta = {TYPE => "scalar", VALUE => $node };
169             } elsif (ref $node eq "SCALAR") {
170 23         102 $meta = {TYPE => "reference", VALUE => $$node };
171             } elsif (ref $node eq "ARRAY") {
172 5         21 $meta = {TYPE => "list", VALUE => $node };
173             } elsif (ref $node eq "HASH") {
174 36         64 my @keys = keys(%{$node});
  36         118  
175 36         189 $meta = {TYPE => "hash", VALUE => \@keys };
176             } elsif (blessed($node) && $node->isa('Connector')) {
177 3         14 $meta = {TYPE => "connector", VALUE => $node };
178             } else {
179 0         0 die "Unsupported node type: " . ref $node;
180             }
181 103         345 return $meta;
182             }
183              
184             sub exists {
185              
186 21     21 1 734 my $self = shift;
187              
188 21         43 my $value = 0;
189 21         38 eval {
190 21         64 $value = defined $self->_get_node( shift );
191             };
192 21         137 return $value;
193              
194             }
195              
196             sub set {
197              
198 9     9 1 53 my $self = shift;
199 9         34 my @path = $self->_build_path_with_prefix( shift );
200              
201 9         22 my $value = shift;
202              
203 9         252 my $ptr = $self->_config();
204              
205 9         29 while (scalar @path > 1) {
206 5         9 my $entry = shift @path;
207 5 100       19 if (!exists $ptr->{$entry}) {
    50          
208 4         13 $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         16 my $entry = shift @path;
216              
217 9 100       23 if (!defined $value) {
218 1         3 delete $ptr->{$entry};
219 1         3 return;
220             }
221              
222 8 50       19 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         20 $ptr->{$entry} = $value;
228 8         30 return 1;
229             }
230              
231              
232 9     9   71091 no Moose;
  9         25  
  9         60  
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