File Coverage

blib/lib/Connector/Proxy/Config/Versioned.pm
Criterion Covered Total %
statement 93 101 92.0
branch 24 34 70.5
condition n/a
subroutine 18 18 100.0
pod 9 9 100.0
total 144 162 88.8


line stmt bran cond sub pod time code
1             # Connector::Proxy::Config::Versioned
2             #
3             # Proxy class for reading Config::Versioned configuration
4             #
5             # Written by Scott Hardin, Martin Bartosch and Oliver Welter
6             # for the OpenXPKI project 2012
7              
8             # Todo - need some more checks on value types
9              
10              
11             use strict;
12 2     2   2447391 use warnings;
  2         18  
  2         66  
13 2     2   22 use English;
  2         4  
  2         50  
14 2     2   10 use Config::Versioned;
  2         3  
  2         16  
15 2     2   715 use Data::Dumper;
  2         6  
  2         54  
16 2     2   16  
  2         4  
  2         106  
17             use Moose;
18 2     2   12 extends 'Connector::Proxy';
  2         10  
  2         15  
19              
20             has '+_config' => (
21             lazy => 1,
22             );
23              
24             has 'version' => (
25             is => 'rw',
26             isa => 'Str',
27             required => 0,
28             builder => 'fetch_head_commit',
29             );
30              
31             my $self = shift;
32              
33 3     3   12 my $config = Config::Versioned->new( { dbpath => $self->LOCATION(), } );
34              
35 3         87 if ( not defined $config ) {
36             return; # try to throw exception
37 3 50       3049 }
38 0         0 $self->version( $config->version() );
39             return $config;
40 3         14 }
41 3         140  
42              
43             my $self = shift;
44             return $self->_config()->version();
45             }
46 3     3 1 8  
47 3         155 my $self = shift;
48             my $path = $self->_build_delimited_cv_path( shift );
49              
50             # We need a change to C:V backend to check if this is a node or not
51 24     24 1 1066 my $val = $self->_config()->get( $path, $self->version() );
52 24         114  
53             $self->_node_not_exists( $path ) unless (defined $val);
54              
55 24         851 return $val;
56             }
57 24 100       195527  
58              
59 24         314 my $self = shift;
60             my $path = $self->_build_delimited_cv_path( shift );
61              
62             # We check if the value is an integer to see if this looks like
63             # an array - This is not bullet proof but should do
64 1     1 1 13  
65 1         7 my $val = $self->_config()->get( $path, $self->version() );
66              
67             return 0 unless( $val );
68              
69             die "requested path looks not like a list" unless( $val =~ /^\d+$/);
70 1         30  
71             return $val;
72 1 50       6390  
73             };
74 1 50       12  
75              
76 1         7 my $self = shift;
77             my $path = $self->_build_delimited_cv_path( shift );
78              
79             # C::V uses an array with numeric keys internally - we use this to check if this is an array
80             my @keys = $self->_config()->get( $path, $self->version() );
81             my @list;
82 1     1 1 3  
83 1         3 if (!@keys) {
84             $self->_node_not_exists( $path ) ;
85             return @list;
86 1         31 };
87 1         6567  
88             foreach my $key (@keys) {
89 1 50       8 if ($key !~ /^\d+$/) {
90 0         0 die "requested path looks not like a list";
91 0         0 }
92             push @list, $self->_config()->get( $path.$self->DELIMITER().$key, $self->version() );
93             }
94 1         4 return @list;
95 4 50       21127 };
96 0         0  
97              
98 4         108 my $self = shift;
99             my $path = $self->_build_delimited_cv_path( shift );
100 1         7049  
101             my @keys = $self->_config()->get( $path, $self->version() );
102              
103             return @{[]} unless(@keys);
104              
105 2     2 1 11 return @keys;
106 2         8  
107             };
108 2         77  
109              
110 2 50       13107 my $self = shift;
  0         0  
111             my $path = $self->_build_delimited_cv_path( shift );
112 2         36  
113             my @keys = $self->_config()->get( $path, $self->version() );
114              
115             return $self->_node_not_exists( $path ) unless(@keys);
116             my $data = {};
117             foreach my $key (@keys) {
118 4     4 1 663 $data->{$key} = $self->_config()->get( $path.$self->DELIMITER().$key, $self->version() );
119 4         15 }
120             return $data;
121 4         125 };
122              
123 4 50       27704  
124 4         9 my $self = shift;
125 4         29 my $path = $self->_build_delimited_cv_path( shift );
126 9         36671  
127             # We need a change to C:V backend to check if this is a node or not
128 4         30781 my $val = $self->_config()->get( $path, $self->version() );
129              
130             $self->_node_not_exists( $path ) unless (defined $val);
131              
132             if (ref $val ne "SCALAR") {
133 1     1 1 3 die "requested path looks not like a reference";
134 1         4 }
135              
136             return $$val;
137 1         32 };
138              
139 1 50       6712  
140             # This can be a very expensive method and includes some guessing
141 1 50       4  
142 0         0 my $self = shift;
143             my $path = $self->_build_delimited_cv_path( shift );
144              
145 1         5 my @keys = $self->_config()->get( $path, $self->version() );
146              
147             return $self->_node_not_exists( $path ) unless( @keys );
148              
149             my $meta = {
150             TYPE => "hash"
151             };
152 173     173 1 419  
153 173         611 # Do some guessing
154             if (@keys == 1) {
155 173         5642 # a redirector reference
156             if (ref $keys[0] eq "SCALAR") {
157 173 100       1441005 $meta->{TYPE} = "reference";
158             $meta->{VALUE} = ${$keys[0]};
159 94         409  
160             # Node with empty value
161             } elsif ($keys[0] eq "") {
162             $meta->{TYPE} = "scalar";
163             $meta->{VALUE} = "";
164 94 100       481 } else {
    100          
165             # probe if there is something "below"
166 69 100       376 my $val = $self->_config()->get( $path . $self->DELIMITER() . $keys[0], $self->version() );
    50          
167 29         105 if (!defined $val) {
168 29         57 $meta->{TYPE} = "scalar";
  29         102  
169             $meta->{VALUE} = $keys[0];
170             } elsif( $keys[0] =~ /^\d+$/) {
171             $meta->{TYPE} = "list";
172 0         0 }
173 0         0 }
174             } elsif( $keys[0] =~ /^\d+$/) {
175             $meta->{TYPE} = "list";
176 40         1173 }
177 40 100       355221  
    100          
178 27         108 return $meta;
179 27         102 }
180              
181 2         9  
182              
183             my $self = shift;
184             my $path = $self->_build_delimited_cv_path( shift );
185 2         7 my $node;
186             eval {
187             $node = $self->_config()->get( $path, $self->version() );
188 94         649 };
189             return defined $node;
190              
191             }
192              
193             # return the path as string as used in C::V using the delimiter of C::V!
194 5     5 1 11  
195 5         12 my $self = shift;
196 5         37 my @path = $self->_build_path_with_prefix( shift );
197 5         8 return join ( $self->_config()->delimiter(), @path );
198 5         119  
199             }
200 5         28374  
201              
202             no Moose;
203             __PACKAGE__->meta->make_immutable;
204              
205             1;
206              
207 211     211   465 =head1 Name
208 211         983  
209 211         6689 Connector::Proxy::Config::Versioned
210              
211             =head1 Description
212              
213             Fetch values ftom the underlying Config::Versioned repository.
214 2     2   14582 On init, the commit id of the head is written into the local
  2         5  
  2         8  
215             version property and all further queries are done against this
216             commit id. You can set the version to be used at any time by passing
217             the commit id (sha1 hash) to C<version>.
218              
219             To advance to the head commit of the underlying repository, use
220             C<fetch_head_commit> to get the id of the head and set it using
221             C<version>
222              
223             =head1 methods
224              
225             =head2 fetch_head_commit
226              
227             Receive the sha1 commit id of the topmost commit of the underlying repository.
228              
229             =head2 version
230             get/set the value of the version used for all get* requests.
231