File Coverage

lib/App/Followme/ConfiguredObject.pm
Criterion Covered Total %
statement 78 84 92.8
branch 22 28 78.5
condition n/a
subroutine 13 14 92.8
pod 3 9 33.3
total 116 135 85.9


line stmt bran cond sub pod time code
1             package App::Followme::ConfiguredObject;
2              
3 24     24   1152 use 5.008005;
  24         90  
4 24     24   134 use strict;
  24         57  
  24         583  
5 24     24   123 use warnings;
  24         55  
  24         787  
6              
7 24     24   173 use Cwd;
  24         60  
  24         20109  
8              
9             our $VERSION = "2.02";
10              
11             #----------------------------------------------------------------------
12             # Create object that returns files in a directory tree
13              
14             sub new {
15 187     187 1 32968 my ($pkg, %configuration) = @_;
16              
17 187         412 my $self = {};
18 187         453 my $cycle = {};
19 187         788 initialize($pkg, $self, $cycle, %configuration);
20              
21 187         992 return $self;
22             }
23              
24             #----------------------------------------------------------------------
25             # Read the default parameter values
26              
27             sub parameters {
28 936     936 1 1482 my ($pkg) = @_;
29              
30             return (
31 936         14288 quick_update => 0,
32             case_sensitivity => 0,
33             top_directory => getcwd(),
34             base_directory => getcwd(),
35             );
36             }
37              
38             #----------------------------------------------------------------------
39             # Update an object's fields from the configuration hash
40              
41             sub add_configurations {
42 679     679 0 1777 my ($self, $pkg, %configuration) = @_;
43              
44 679         1793 foreach my $field ($self->all_fields(\%configuration)) {
45 595         1389 $self->{$field} = $configuration{$field};
46             }
47              
48 679         1364 return;
49             }
50              
51             #----------------------------------------------------------------------
52             # Create subobjects for any parameter ending in _pkg
53              
54             sub add_subpackages {
55 679     679 0 1746 my ($self, %configuration) = @_;
56              
57 679         1232 foreach my $field ($self->all_fields($self)) {
58 2268         3726 my $subpkg = $self->{$field};
59 2268 100       5346 next unless $field =~ s/_pkg$//;
60              
61 134 50       8315 eval "require $subpkg" or die "Module not found: $subpkg\n";
62              
63 134 100       1137 if ($subpkg->isa('App::Followme::ConfiguredObject')) {
    50          
64 127         603 $self->{$field} = $subpkg->new(%configuration);
65             } elsif ($subpkg->can('new')) {
66 7         41 $self->{$field} = $subpkg->new();
67             } else {
68 0         0 $self->{$field} = $subpkg;
69             }
70             }
71              
72 679         1446 return;
73             }
74              
75             #----------------------------------------------------------------------
76             # Get the configuration fields that apply to this package
77              
78             sub all_fields {
79 1358     1358 0 2167 my ($self, $configuration) = @_;
80              
81 1358         2001 my @fields = ();
82 1358 50       2544 if (defined $configuration) {
83 1358         2064 my $pkg = ref $self;
84 1358         2662 my %parameters = $pkg->parameters();
85              
86 1358         4555 foreach my $field (keys %$configuration) {
87 8411 100       14662 next if ref $configuration->{$field};
88 8060 100       15843 push(@fields, $field) if exists $parameters{$field};;
89             }
90             }
91              
92 1358         3244 return @fields;
93             }
94              
95             #----------------------------------------------------------------------
96             # Remove prefixes from config fields that match the package name
97              
98             sub filter_configuration {
99 679     679 0 1754 my ($pkg, %configuration) = @_;
100              
101 679         1992 my %parameters = $pkg->parameters();
102 679         1984 my @config_keys = keys %configuration;
103              
104 679         1351 for my $field (@config_keys) {
105 2409         4711 my @configuration_fields = split('::', $field);
106 2409         3549 my $config_field = pop(@configuration_fields);
107 2409 100       5066 next unless @configuration_fields;
108              
109 4         9 my @pkg_fields = split('::', $pkg);
110              
111 4         7 my $match = 1;
112 4         9 while (@configuration_fields) {
113 7         9 my $subfield = pop(@configuration_fields);
114 7         10 my $pkg_field = pop(@pkg_fields);
115              
116 7 50       19 if ($pkg_field ne $subfield) {
117 0         0 $match = 0;
118 0         0 last;
119             }
120             }
121              
122 4 50       6 if ($match) {
123 4         9 $configuration{$config_field} = $configuration{$field};
124 4         8 delete $configuration{$field};
125             }
126             }
127              
128 679         2990 return %configuration;
129             }
130              
131             #----------------------------------------------------------------------
132             # Extract the package field name from the configuration field name
133              
134             sub get_pkg_field {
135 0     0 0 0 my ($self, $field) = @_;
136 0         0 my @configuration_fields = split('::', $field);
137 0         0 return pop(@configuration_fields);
138             }
139              
140             #----------------------------------------------------------------------
141             # Initialize the object by populating its hash
142              
143             sub initialize {
144 679     679 0 2056 my ($pkg, $self, $cycle, %configuration) = @_;
145 679 100       1570 %configuration = () unless %configuration;
146 679 50       1507 return if $cycle->{$pkg};
147              
148 24     24   219 no strict 'refs';
  24         95  
  24         5611  
149 679         2451 %configuration = $pkg->filter_configuration(%configuration);
150 679         1226 initialize($_, $self, $cycle, %configuration) foreach @{"${pkg}::ISA"};
  679         3602  
151 679         1477 $cycle->{$pkg} = 1;
152              
153 679         1823 my %parameters = $pkg->parameters();
154 679         2525 while (my ($key, $value) = each(%parameters)) {
155 2806 100       9350 $self->{$key} = $value if length $value;
156             }
157              
158 679         1234 $self = bless($self, $pkg);
159              
160 679         2427 $self->add_configurations($pkg, %configuration);
161 679         2485 $self->add_subpackages(%configuration);
162              
163 679 100       1023 $self->setup(%configuration) if defined &{"${pkg}::setup"};
  679         4203  
164 679         2036 return;
165             }
166              
167             #----------------------------------------------------------------------
168             # Set up object fields (stub)
169              
170             sub setup {
171 187     187 1 453 my ($self) = @_;
172 187         319 return;
173             }
174              
175             1;
176             __END__
177              
178             =encoding utf-8
179              
180             =head1 NAME
181              
182             App::Followme::ConfiguredObject - Base class for App::Followme classes
183              
184             =head1 SYNOPSIS
185              
186             use App::Followme::ConfiguredObject;
187             my $obj = App::Followme::ConfiguredObjects->new($configuration);
188              
189             =head1 DESCRIPTION
190              
191             This class creates a new configured object. All classes in App::Followme are
192             subclassed from it. The new method creates a new object and initializes the
193             parameters from the configuration file.
194              
195             =over 4
196              
197             =item $obj = ConfiguredObject->new($configuration);
198              
199             Create a new object from the configuration. The configuration is a reference to
200             a hash containing fields with the same names as the object parameters. Fields
201             in the configuration whose name does not match an object parameter are ignored.
202             If a configuration field ends in "_pkg", its value is assumed to be the name of
203             a subpackage, which is is created and stored in a field whose name is stripped
204             of the "_pkg" suffix.
205              
206             =item %parameters = $self->parameters();
207              
208             Returns a hash of the default values of the object's parameters.
209              
210             =item $self->setup(%configuration);
211              
212             Sets those parameters of the object which are computed when the object is
213             initialized.
214              
215             =back
216              
217             =head1 CONFIGURATION
218              
219             The following fields in the configuration file are used in this class and every
220             class based on it:
221              
222             =over 4
223              
224             =item base_directory
225              
226             The directory containing the configuration file that loads the class. The
227             default value is the current directory.
228              
229             =item case_sensitvity
230              
231             Boolean flag that indicates if filenames on this operating system
232             are case sensitive. The default value is false.
233              
234             =item quick_mode
235              
236             A flag indicating application is run in quick mode.
237              
238             =item top_directory
239              
240             The top directory of the website. The default value is the current directory.
241              
242             =back
243              
244             =head1 LICENSE
245              
246             Copyright (C) Bernie Simon.
247              
248             This library is free software; you can redistribute it and/or modify
249             it under the same terms as Perl itself.
250              
251             =head1 AUTHOR
252              
253             Bernie Simon E<lt>bernie.simon@gmail.comE<gt>
254              
255             =cut