File Coverage

lib/UR/ModuleConfig.pm
Criterion Covered Total %
statement 12 101 11.8
branch 0 32 0.0
condition 0 6 0.0
subroutine 4 9 44.4
pod 4 4 100.0
total 20 152 13.1


line stmt bran cond sub pod time code
1             # Manage dynamic configuration of modules.
2              
3             package UR::ModuleConfig;
4              
5             =pod
6              
7             =head1 NAME
8              
9             UR::ModuleConfig - manage dynamic configuration of modules.
10              
11             =head1 SYNOPSIS
12              
13             package MyModule;
14             use base qw(UR::ModuleConfig);
15              
16             MyModule->config(%conf);
17             $val = MyModule->config('key');
18             %conf = MyModule->config;
19              
20             =head1 DESCRIPTION
21              
22             This module manages the configuration for modules. Configurations can
23             be read from files or set dynamically. Modules wishing to use the
24             configuration methods should inherit from the module.
25              
26             =cut
27              
28             # set up package
29             require 5.006_000;
30 266     266   987 use warnings;
  266         336  
  266         7487  
31 266     266   868 use strict;
  266         297  
  266         9095  
32             require UR;
33             our $VERSION = "0.46"; # UR $VERSION;;
34 266     266   881 use base qw(UR::ModuleBase);
  266         320  
  266         18861  
35 266     266   1020 use IO::File;
  266         313  
  266         228449  
36              
37             =pod
38              
39             =head2 METHODS
40              
41             The methods deal with managing configuration.
42              
43             =cut
44              
45             # hash containing all configuration information
46             our %config;
47              
48             # create a combined configuration hash from inheritance tree
49             sub _inherit_config
50             {
51 0     0     my $self = shift;
52 0   0       my $class = ref($self) || $self;
53              
54 0           my %cfg;
55              
56             # get all packages inherited from
57 0           my @inheritance = $self->inheritance;
58              
59             # reverse loop through inheritance tree and construct config
60 0           foreach my $cls (reverse(@inheritance))
61             {
62 0 0         if (exists($config{$cls}))
63             {
64             # add hash, overriding previous values
65 0           %cfg = (%cfg, %{$config{$cls}});
  0            
66             }
67             }
68              
69             # now add the current class config
70 0 0         if (exists($config{$class}))
71             {
72 0           %cfg = (%cfg, %{$config{$class}});
  0            
73             }
74              
75             # now add the object config
76 0 0         if (ref($self))
77             {
78             # add the objects config
79 0 0         if (exists($config{"$class;$self"}))
80             {
81 0           %cfg = (%cfg, %{$config{"$class;$self"}});
  0            
82             }
83             }
84              
85 0           return %cfg;
86             }
87              
88             =pod
89              
90             =over 4
91              
92             =item config
93              
94             MyModule->config(%config);
95             $val = MyModule->config('key');
96             %conf = MyModule->config;
97              
98             my $obj = MyModule->new;
99             $obj->config(%config);
100              
101             This method can be called three ways, as either a class or object
102             method. The first method takes a hash as its argument and sets the
103             configuration parameters given in the hash. The second method takes a
104             single argument which should be one of the keys of the hash that set
105             the config parameters and returns the value of that config hash key.
106             The final method takes no arguments and returns the entire
107             configuration hash.
108              
109             When called as an object method, the config for both the object and
110             all classes in its inheritance hierarchy are referenced, with the
111             object config taking precedence over class methods and class methods
112             closer to the object (first in the @ISA array) taking precedence over
113             those further away (later in the @ISA array). When called as a class
114             method, the same procedure is used, except no object configuration is
115             referenced.
116              
117             Do not use configuration keys that begin with an underscore (C<_>).
118             These are reserved for internal use.
119              
120             =back
121              
122             =cut
123              
124             sub config
125             {
126 0     0 1   my $self = shift;
127 0   0       my $class = ref($self) || $self;
128              
129             # handle both object and class configuration
130 0           my $target;
131 0 0         if (ref($self))
132             {
133             # object config
134 0           $target = "$class;$self";
135             }
136             else
137             {
138             # class config
139 0           $target = $self;
140             }
141              
142             # lay claim to the modules configuration
143 0           $config{$target}{_Manager} = __PACKAGE__;
144              
145             # see if values are being set
146 0 0         if (@_ > 1)
147             {
148             # set values in config hash, overriding any current values
149 0           my (%opts) = @_;
150 0           %{$config{$target}} = (%{$config{$target}}, %opts);
  0            
  0            
151 0           return 1;
152             }
153             # else they want one key or the whole hash
154              
155             # store config for object and inheritance tree
156 0           my %cfg = $self->_inherit_config;
157              
158             # see how we were called
159 0 0         if (@_ == 1)
160             {
161             # return value of key
162 0           my ($key) = @_;
163             # make sure hash key exists
164 0           my $val;
165 0 0         if (exists($cfg{$key}))
166             {
167 0           $self->debug_message("config key $key exists");
168 0           $val = $cfg{$key};
169             }
170             else
171             {
172 0           $self->error_message("config key $key does not exist");
173 0           return;
174             }
175 0           return $val;
176             }
177             # else return the entire config hash
178 0           return %cfg;
179             }
180              
181             =pod
182              
183             =over 4
184              
185             =item check_config
186              
187             $obj->check_config($key);
188              
189             This method checks to see if a value is set. Unlike config, it does
190             not issue a warning if the key is not set. If the key is not set,
191             C is returned. If the key has been set, the value of the key
192             is returned (which may be C).
193              
194             =back
195              
196             =cut
197              
198             sub check_config
199             {
200 0     0 1   my $self = shift;
201              
202 0           my ($key) = @_;
203              
204             # get config for inheritance tree
205 0           my %cfg = $self->_inherit_config;
206              
207 0 0         if (exists($cfg{$key}))
208             {
209 0           $self->debug_message("configuration key $key set: $cfg{$key}");
210 0           return $cfg{$key};
211             }
212             # else
213 0           $self->debug_message("configuration key $key not set");
214 0           return;
215             }
216              
217             =pod
218              
219             =over 4
220              
221             =item default_config
222              
223             $class->default_config(%defaults);
224              
225             This method allows the developer to set configuration values, only if
226             they are not already set.
227              
228             =back
229              
230             =cut
231              
232             sub default_config
233             {
234 0     0 1   my $self = shift;
235              
236 0           my (%opts) = @_;
237              
238             # get config for inheritance tree
239 0           my %cfg = $self->_inherit_config;
240              
241             # loop through arguments
242 0           while (my ($k, $v) = each(%opts))
243             {
244             # see is config value is already set
245 0 0         if (exists($cfg{$k}))
246             {
247 0           $self->debug_message("config $k already set");
248 0           next;
249             }
250 0           $self->debug_message("setting default for $k");
251              
252             # set config key
253 0           $self->config($k => $v);
254             }
255              
256 0           return 1;
257             }
258              
259             =pod
260              
261             =over 4
262              
263             =item config_file
264              
265             $rv = $class->config_file(path => $path);
266             $rv = $class->config_file(handle => $fh);
267              
268             This method reads in the given file and expects key-value pairs, one
269             per line. The key and value should be separated by an equal sign,
270             C<=>, with optional surrounding space. It currently only handles
271             single value values.
272              
273             The method returns true upon success, C on failure.
274              
275             =back
276              
277             =cut
278              
279             sub config_file
280             {
281 0     0 1   my $self = shift;
282              
283 0           my (%opts) = @_;
284              
285 0           my $fh;
286 0 0         if ($opts{path})
    0          
287             {
288             # make sure file is ok
289 0 0         if (-f $opts{path})
290             {
291 0           $self->debug_message("config file exists: $opts{path}");
292             }
293             else
294             {
295 0           $self->error_message("config file does not exist: $opts{path}");
296 0           return;
297             }
298 0 0         if (-r $opts{path})
299             {
300 0           $self->debug_message("config file is readable: $opts{path}");
301             }
302             else
303             {
304 0           $self->error_message("config file is not readable: $opts{path}");
305 0           return;
306             }
307              
308             # open file
309 0           $fh = IO::File->new("<$opts{path}");
310 0 0         if (defined($fh))
311             {
312 0           $self->debug_message("opened config file for reading: $opts{path}");
313             }
314             else
315             {
316             $self->error_message("failed to open config file for reading: "
317 0           . $opts{path});
318 0           return;
319             }
320             }
321             elsif ($opts{handle})
322             {
323 0           $fh = $opts{handle};
324             }
325             else
326             {
327 0           $self->error_message("no config file input specified");
328 0           return;
329             }
330              
331             # read through file
332 0           my %fconfig;
333 0           while (defined(my $line = $fh->getline))
334             {
335             # clean up
336 0           chomp($line);
337 0           $line =~ s/\#.*//;
338 0           $line =~ s/^\s*//;
339 0           $line =~ s/\s*$//;
340 0 0         next unless $line =~ m/\S/;
341              
342             # parse
343 0           my ($k, $v) = split(m/\s*=\s*/, $line, 2);
344 0           $fconfig{$k} = $v;
345             }
346 0           $fh->close;
347              
348             # update config
349 0           return $self->config(%fconfig);
350             }
351              
352             1;
353              
354             #$Header$