File Coverage

lib/App/Service.pm
Criterion Covered Total %
statement 31 126 24.6
branch 6 82 7.3
condition 1 26 3.8
subroutine 6 13 46.1
pod 9 9 100.0
total 53 256 20.7


line stmt bran cond sub pod time code
1              
2             #############################################################################
3             ## $Id: Service.pm 13305 2009-09-11 13:50:28Z spadkins $
4             #############################################################################
5              
6             package App::Service;
7             $VERSION = (q$Revision: 13305 $ =~ /(\d[\d\.]*)/)[0]; # VERSION numbers generated by svn
8              
9 6     6   28 use strict;
  6         12  
  6         223  
10              
11 6     6   100 use App;
  6         12  
  6         2873  
12              
13             =head1 NAME
14              
15             App::Service - Provides core methods for App-Context Services
16              
17             =head1 SYNOPSIS
18              
19             use App::Service;
20              
21             # never really used, because this is a base class
22             %named = (
23             # named args would go here
24             );
25             $service = App::Service->new(%named);
26              
27             =head1 DESCRIPTION
28              
29             The App::Service class is a base class for all App-Context services.
30              
31             * Throws: App::Exception
32             * Since: 0.01
33              
34             =cut
35              
36             #############################################################################
37             # CONSTRUCTOR METHODS
38             #############################################################################
39              
40             =head1 Constructor Methods:
41              
42             =cut
43              
44             #############################################################################
45             # Method: new()
46             #############################################################################
47              
48             =head2 new()
49              
50             This constructor is used to create all objects which are App-Context services.
51             Customized behavior for a particular service is achieved by overriding
52             the _init() method.
53              
54             * Signature: $service = App::Service->new(%named)
55             * Return: $service App::Service
56             * Throws: App::Exception
57             * Since: 0.01
58              
59             Sample Usage: (never used because this is a base class, but the
60             constructors of all services follow these rules)
61            
62             * If the number of arguments is odd, the first arg is the service name
63             (otherwise, "default" is assumed)
64             * If there are remaining arguments, they are variable/value pairs
65             * If there are no arguments at all, the "default" name is assumed
66             * If a "name" was supplied using any of these methods,
67             the master config is consulted to find the config for this
68             particular service instance (service_type/name).
69              
70             $service = App::Service->new(); # assumes "default" name
71             $service = App::Service->new("srv1"); # instantiate named service
72             $service = App::Service->new( # "default" with named args
73             arg1 => 'value1',
74             arg2 => 'value2',
75             );
76              
77             =cut
78              
79             sub new {
80 1 50   1 1 508 &App::sub_entry if ($App::trace);
81 1         2 my $this = shift;
82 1   33     9 my $class = ref($this) || $this;
83 1         2 my ($self, $context, $type);
84              
85 1         6 $context = App->context();
86 1         4 $type = $class->service_type();
87 1 50       4 if ($#_ % 2 == 0) { # odd number of args
88 1         16 $self = $context->service($type, @_, "class", $class);
89             }
90             else { # even number of args (
91 0         0 $self = $context->service($type, "default", @_, "class", $class);
92             }
93 1 50       3 &App::sub_exit($self) if ($App::trace);
94 1         3 return $self;
95             }
96              
97             #############################################################################
98             # Method: service_type()
99             #############################################################################
100              
101             =head2 service_type()
102              
103             Returns the service type (i.e. CallDispatcher, Repository, SessionObject, etc.).
104              
105             * Signature: $service_type = App::Service->service_type();
106             * Param: void
107             * Return: $service_type string
108             * Since: 0.01
109              
110             $service_type = $service->service_type();
111              
112             =cut
113              
114             sub service_type () { 'Service'; }
115              
116             #############################################################################
117             # Method: content()
118             #############################################################################
119              
120             =head2 content()
121              
122             * Signature: $content = $self->content();
123             * Param: void
124             * Return: $content any
125             * Throws: App::Exception
126             * Since: 0.01
127              
128             $content = $so->content();
129             if (ref($content)) {
130             App::Reference->print($content);
131             print "\n";
132             }
133             else {
134             print $content, "\n";
135             }
136              
137             =cut
138              
139             sub content {
140 0 0   0 1 0 &App::sub_entry if ($App::trace);
141 0         0 my $self = shift;
142 0         0 my $content = $self->internals();
143 0 0       0 &App::sub_exit($content) if ($App::trace);
144 0         0 return($content);
145             }
146              
147             #############################################################################
148             # content_type()
149             #############################################################################
150              
151             =head2 content_type()
152              
153             * Signature: $content_type = $service->content_type();
154             * Param: void
155             * Return: $content_type string
156             * Throws: App::Exception
157             * Since: 0.01
158              
159             Sample Usage:
160              
161             $content_type = $service->content_type();
162              
163             =cut
164              
165             sub content_type {
166 0 0   0 1 0 &App::sub_entry if ($App::trace);
167 0         0 my $content_type = 'text/plain';
168 0 0       0 &App::sub_exit($content_type) if ($App::trace);
169 0         0 return($content_type);
170             }
171              
172             #############################################################################
173             # content_description()
174             #############################################################################
175              
176             =head2 content_description()
177              
178             * Signature: $content_description = $service->content_description();
179             * Param: void
180             * Return: $content_description string
181             * Throws: App::Exception
182             * Since: 0.01
183              
184             Provide a description of the content which is useful for diagnostic purposes
185             (such as for the timing log implemented in App::Context::HTTP).
186              
187             This method can be overridden by an application-specific service such as a
188             web application user interface widget to provide more useful information
189             in the description.
190              
191             Sample Usage:
192              
193             $content_description = $service->content_description();
194              
195             =cut
196              
197             sub content_description {
198 0 0   0 1 0 &App::sub_entry if ($App::trace);
199 0         0 my ($self) = @_;
200 0         0 my $class = ref($self);
201 0         0 my $content_description = "$class($self->{name})";
202 0 0       0 &App::sub_exit($content_description) if ($App::trace);
203 0         0 return($content_description);
204             }
205              
206             #############################################################################
207             # Method: internals()
208             #############################################################################
209              
210             =head2 internals()
211              
212             * Signature: $guts = $self->internals();
213             * Param: void
214             * Return: $guts {}
215             * Throws: App::Exception
216             * Since: 0.01
217              
218             $guts = $so->internals();
219             App::Reference->print($guts);
220             print App::Reference->dump($guts), "\n";
221              
222             Copy the internals of the current SessionObject to a new hash and return
223             a reference to that hash for debugging purposes. The resulting hash
224             reference may be printed using Data::Dumper (or App::Reference).
225             The refe
226              
227             =cut
228              
229             sub internals {
230 0 0   0 1 0 &App::sub_entry if ($App::trace);
231 0         0 my ($self) = @_;
232 0         0 my %copy = %$self;
233 0         0 delete $copy{context};
234 0         0 delete $copy{dict};
235 0 0       0 &App::sub_exit(\%copy) if ($App::trace);
236 0         0 return \%copy;
237             }
238              
239             #############################################################################
240             # dump()
241             #############################################################################
242              
243             =head2 dump()
244              
245             * Signature: $perl = $service->dump();
246             * Param: void
247             * Return: $perl text
248             * Throws: App::Exception
249             * Since: 0.01
250              
251             Sample Usage:
252              
253             $service = $context->repository();
254             print $service->dump(), "\n";
255              
256             =cut
257              
258 6     6   34 use Data::Dumper;
  6         19  
  6         6439  
259              
260             sub dump {
261 5     5 1 8214 my ($self, $ref) = @_;
262 5         10 my ($copy, $data, $name);
263 5 50       13 if ($ref) {
264 0 0       0 if (!ref($ref)) {
    0          
265 0         0 $data = $ref;
266 0         0 $name = "scalar";
267             }
268             elsif (ref($ref) eq "ARRAY") {
269 0         0 $data = [];
270 0         0 my ($r);
271 0         0 foreach my $d (@$ref) {
272 0         0 $r = ref($d);
273 0 0 0     0 if (!$r || $r eq "ARRAY" || $r eq "SCALAR") {
    0 0        
      0        
274 0         0 push(@$data, $d);
275             }
276             elsif (!$d->{context} && !$d->{_repository}) {
277 0         0 push(@$data, $d);
278             }
279             else {
280 0         0 $copy = { %$d };
281 0 0       0 $copy->{context} = "" if ($copy->{context}); # don't dump the reference to the context itself (Services)
282 0 0       0 $copy->{_repository} = "" if ($copy->{_repository}); # don't dump the reference to the repository (RepositoryObjects)
283 0         0 push(@$data, $copy);
284             }
285             }
286 0         0 $data = [ $data ];
287 0         0 $name = "array";
288             }
289             else {
290 0         0 $copy = { %$ref };
291 0 0       0 $copy->{context} = "" if ($copy->{context}); # don't dump the reference to the context itself (Services)
292 0 0       0 $copy->{_repository} = "" if ($copy->{_repository}); # don't dump the reference to the repository (RepositoryObjects)
293 0         0 $data = [ $copy ];
294 0         0 $name = "hash";
295             }
296             }
297             else {
298 5         33 $copy = { %$self };
299 5 50       25 $copy->{context} = "" if ($copy->{context}); # don't dump the reference to the context itself (Services)
300 5 50       13 $copy->{_repository} = "" if ($copy->{_repository}); # don't dump the reference to the repository (RepositoryObjects)
301 5         13 $data = [ $copy ];
302 5         24 $name = $self->service_type() . "__" . $self->{name};
303             }
304 5         41 my $d = Data::Dumper->new($data, [ $name ]);
305 5         207 $d->Indent(1);
306 5         74 return $d->Dump();
307             }
308              
309             #############################################################################
310             # print()
311             #############################################################################
312              
313             =head2 print()
314              
315             * Signature: $service->print();
316             * Param: void
317             * Return: void
318             * Throws: App::Exception
319             * Since: 0.01
320              
321             Sample Usage:
322              
323             $service->print();
324              
325             =cut
326              
327             sub print {
328 0     0 1 0 my $self = shift;
329 0         0 print $self->dump();
330             }
331              
332             #############################################################################
333             # substitute()
334             #############################################################################
335              
336             =head2 substitute()
337              
338             * Signature: $result = $service->substitute($target);
339             * Signature: $result = $service->substitute($target, $values);
340             * Param: $target HASH,string
341             * Param: $values HASH
342             * Return: $result string
343             * Throws: App::Exception
344             * Since: 0.01
345              
346             Sample Usage:
347              
348             $welcome_message = $service->substitute("Welcome, {default-user}");
349              
350             my $auto_params = { user => "{default-user}", org_id => "{org_id}", };
351             my $auto_values = { org_id => 1, };
352             $params = $service->substitute($auto_params, $auto_values);
353              
354             The substitute() method scans the $target string (or hash of strings) for
355             instances of variables (i.e. "{varname}") and makes substitutions.
356             It makes substitutions from a hash of $values if provided or from the
357             values of SessionObjects of the same name.
358              
359             The substitute() method returns a string (or hash of strings) which is the
360             result of the substitution.
361              
362             =cut
363              
364             sub substitute {
365 0 0   0 1 0 &App::sub_entry if ($App::trace);
366 0         0 my ($self, $text, $values, $options) = @_;
367 0         0 my ($phrase, $var, $value, $context, $default);
368 0         0 $context = $self->{context};
369 0 0       0 $values = {} if (! defined $values);
370              
371 0 0       0 if (ref($text) eq "HASH") {
372 0         0 my ($hash, $newhash);
373 0         0 $hash = $text; # oops, not text, but a hash of text values
374 0         0 $newhash = {}; # prepare a new hash for the substituted values
375 0         0 foreach $var (keys %$hash) {
376 0         0 $newhash->{$var} = $self->substitute($hash->{$var}, $values, $options);
377             }
378 0 0       0 &App::sub_exit($newhash) if ($App::trace);
379 0         0 return($newhash); # short-circuit this whole process
380             }
381              
382 0 0       0 my $undef_value = (defined $options->{undef_value}) ? $options->{undef_value} : "";
383              
384             # looking for patterns like the following: {user} {user:Guest}
385 0         0 while ( $text =~ /\{([^\{\}:]+)(:[^\{\}]+)?\}/ ) { # vars of the form {var}
386 0         0 $var = $1;
387 0         0 $default = $2;
388 0 0       0 if (defined $values->{$var}) {
389 0         0 $value = $values->{$var};
390 0 0       0 $value = join(",", @$value) if (ref($value) eq "ARRAY");
391             }
392             else {
393 0         0 $value = $context->so_get($var);
394 0 0       0 $value = join(",", @$value) if (ref($value) eq "ARRAY");
395             }
396 0 0 0     0 if ((! defined $value || $value eq "") && $default ne "") {
    0 0        
397 0         0 $default =~ s/^://;
398 0         0 $value = $default;
399             }
400             elsif (!defined $value) {
401 0         0 $value = $undef_value;
402             }
403 0         0 $text =~ s/\{$var(:[^\{\}]+)?\}/$value/g;
404             }
405 0 0       0 &App::sub_exit($text) if ($App::trace);
406 0         0 $text;
407             }
408              
409             #############################################################################
410             # get_sym_label()
411             #############################################################################
412              
413             =head2 get_sym_label()
414              
415             * Signature: $label = $service->get_sym_label($sym);
416             * Signature: $label = $service->get_sym_label($sym, $include_breaks, $label_dict, $lang_dict);
417             * Param: $sym string
418             * Param: $include_breaks boolean
419             * Param: $label_dict HASH
420             * Param: $lang_dict HASH
421             * Return: $label string
422              
423             The get_sym_label() method turns a symbol (i.e. "begin_eff_dt") into a label
424             (i.e. "Begin
Effective
Date"). This label is suitable for use in
425             HTML drop-down lists and table column headings.
426              
427             =cut
428              
429             sub get_sym_label {
430 0 0   0 1 0 &App::sub_entry if ($App::trace);
431 0         0 my ($self, $sym, $include_breaks, $label_dict, $lang_dict) = @_;
432 0         0 my ($label);
433 0 0 0     0 $label = $label_dict->{$sym}{label} if ($label_dict && exists $label_dict->{$sym});
434 0 0       0 if (! defined $label) {
435 0 0       0 if (!$lang_dict) {
436 0         0 my $context = $self->{context};
437 0         0 my $default_object = $context->session_object();
438 0   0     0 my $lang = $default_object->{lang} || "en";
439 0         0 $lang_dict = $default_object->{dict}{$lang};
440             }
441 0 0       0 if ($lang_dict) {
442 0         0 $label = $lang_dict->{$sym};
443             }
444             }
445 0 0       0 if (! defined $label) {
446 0         0 my @part = split(/_/, $sym);
447 0 0       0 my $separator = $include_breaks ? "
" : " ";
448 0         0 for (my $i = 0; $i <= $#part; $i++) {
449 0   0     0 $part[$i] = $lang_dict->{$part[$i]} || ucfirst($part[$i]);
450             }
451 0         0 $label = join($separator, @part);
452             }
453 0 0       0 &App::sub_exit($label) if ($App::trace);
454 0         0 return ($label);
455             }
456              
457             #############################################################################
458             # PROTECTED METHODS
459             #############################################################################
460              
461             =head1 Protected Methods:
462              
463             The following methods are intended to be called by subclasses of the
464             current class.
465              
466             =cut
467              
468             #############################################################################
469             # Method: _init()
470             #############################################################################
471              
472             =head2 _init()
473              
474             The _init() method is called from within the standard Service
475             constructor.
476             It allows subclasses of the Service to customize the behavior of the
477             constructor by overriding the _init() method.
478             The _init() method in this class simply calls the _init()
479             method to allow each service instance to initialize itself.
480              
481             * Signature: _init($named)
482             * Param: $named {} [in]
483             * Return: void
484             * Throws: App::Exception
485             * Since: 0.01
486              
487             Sample Usage:
488              
489             $service->_init(\%args);
490              
491             =cut
492              
493             sub _init {
494 6     6   25 my ($self, $args) = @_;
495             }
496              
497             =head1 ACKNOWLEDGEMENTS
498              
499             * Author: Stephen Adkins
500             * License: This is free software. It is licensed under the same terms as Perl itself.
501              
502             =head1 SEE ALSO
503              
504             L|App>,
505             L|App::Context>,
506             L|App::Conf>
507              
508             =cut
509              
510             1;
511