File Coverage

lib/App/SessionObject.pm
Criterion Covered Total %
statement 29 195 14.8
branch 5 152 3.2
condition 0 38 0.0
subroutine 7 25 28.0
pod 19 19 100.0
total 60 429 13.9


line stmt bran cond sub pod time code
1              
2             #############################################################################
3             ## $Id: SessionObject.pm 9450 2007-04-25 14:58:50Z spadkins $
4             #############################################################################
5              
6             package App::SessionObject;
7             $VERSION = (q$Revision: 9450 $ =~ /(\d[\d\.]*)/)[0]; # VERSION numbers generated by svn
8              
9 1     1   5 use App;
  1         1  
  1         21  
10 1     1   435 use App::Service;
  1         3  
  1         37  
11             @ISA = ( "App::Service" );
12              
13 1     1   7 use strict;
  1         3  
  1         31  
14              
15 1     1   105290 use Date::Parse;
  1         3579  
  1         174  
16 1     1   10 use Date::Format;
  1         2  
  1         3304  
17              
18             =head1 NAME
19              
20             App::SessionObject - Interface for configurable, stateful objects
21              
22             =head1 SYNOPSIS
23              
24             use App;
25              
26             $context = App->context();
27             $session_object = $context->service("SessionObject"); # or ...
28             $session_object = $context->session_object();
29              
30             =head1 DESCRIPTION
31              
32             A SessionObject is an object that can be manipulated
33             without having to worry about its lifecycle (i.e. persistence,
34             saving and restoring state, etc.) or its location (local or remote).
35              
36             =cut
37              
38             #############################################################################
39             # CLASS GROUP
40             #############################################################################
41              
42             =head1 Class Group: SessionObject
43              
44             The following classes might be a part of the SessionObject Class Group.
45              
46             =over
47              
48             =item * Class: App::SessionObject
49              
50             =item * Class: App::SessionObject::Entity
51             - entity session_objects are business objects (like EJB)
52              
53             =item * Class: App::SessionObject::Entity::Repository
54             - a local entity session_object stored in a Repository
55              
56             =item * Class: App::SessionObject::Entity::SOAP
57             - a remote entity session_object, accessed via SOAP
58              
59             =item * Class: App::SessionObject::HTML
60             - user interface session_objects displayed on a browser in HTML
61              
62             =item * Class: App::SessionObject::Curses
63             - user interface session_objects displayed on a terminal using Curses
64              
65             =item * Class: App::SessionObject::Gtk
66             - user interface session_objects displayed in X11 using Gtk
67              
68             =item * Class: App::SessionObject::Tk
69             - user interface session_objects displayed in X11 using Tk
70              
71             =item * Class: App::SessionObject::WxPerl
72             - user interface session_objects displayed on Windows using wxPerl
73              
74             =back
75              
76             A SessionObject is an object that can be manipulated
77             without having to worry about its lifecycle (i.e. persistence,
78             saving and restoring state, etc.) or its location (local or remote).
79              
80             A SessionObject is a App Service, and it inherits all of the features of
81             App Services.
82              
83             * Each SessionObject may be identified by a unique (text) name
84             * Entity SessionObject are kept separate from UI SessionObject by naming convention
85             * SessionObject are accessed by requesting them by name from the Context
86             * SessionObject have attributes (which may be references to complex data structures)
87             * Attributes of SessionObject are accessed via get()/set() methods
88             * get($attribute) is equivalent to $self->{$attribute} (but not set())
89             * Attributes may be defaulted in the code that first accesses the SessionObject,
90             configured in the Config file, or overridden at runtime for the
91             duration of the Session
92              
93             A user interface SessionObject also has a display() method to display
94             the SessionObject on the user agent.
95             The values that are set are stored in the user's Session, so
96             every user Session has a unique copy of every user interface
97             SessionObject.
98              
99             An entity SessionObject is shared between all user Sessions.
100             It maintains its state in a shared data store such as a
101             Repository.
102              
103             =cut
104              
105             #############################################################################
106             # CLASS
107             #############################################################################
108              
109             =head1 Class: App::SessionObject
110              
111             A SessionObject Service is a means by which an object can be manipulated
112             without having to worry about its lifecycle (i.e. persistence,
113             saving and restoring state, etc.) or its location (local or remote).
114              
115             * Throws: App::Exception::SessionObject
116             * Since: 0.01
117              
118             =cut
119              
120             #############################################################################
121             # CONSTRUCTOR METHODS
122             #############################################################################
123              
124             =head1 Constructor Methods:
125              
126             =cut
127              
128             #############################################################################
129             # new()
130             #############################################################################
131              
132             =head2 new()
133              
134             The constructor is inherited from
135             L|App::Service/"new()">.
136              
137             =cut
138              
139             #############################################################################
140             # _init()
141             #############################################################################
142              
143             =head2 _init()
144              
145             The _init() method is called from within the standard Service
146             constructor.
147             Common to all SessionObject initializations, is the absorption of container
148             attributes. "Absorbable attributes" from the session_object are copied from
149             the container session_object to the initialized session_object.
150              
151             * Signature: _init($named)
152             * Param: $named {} [in]
153             * Return: void
154             * Throws: App::Exception
155             * Since: 0.01
156              
157             Sample Usage:
158              
159             $service->_init(\%args);
160              
161             =cut
162              
163             sub _init {
164 6 50   6   20 &App::sub_entry if ($App::trace);
165 6         15 my ($self, $args) = @_;
166 6         8 my ($name, $absorbable_attribs, $container, $attrib);
167              
168 6         25 $name = $self->{name};
169 6         20 $absorbable_attribs = $self->absorbable_attribs();
170 6         8 $container = "default";
171 6 50       31 if ($name =~ /^(.+)-[a-zA-Z][a-zA-Z0-9_]*$/) {
172 0         0 $container = $1;
173             }
174              
175             # absorb attributes of the container config if ...
176             # TODO: sort out whether we need to absorb attributes more often
177             # (i.e. push model rather than a pull model)
178              
179 6 50       17 if ($absorbable_attribs) { # ... there are known attributes to absorb
180              
181             # notice a recursion here on containers
182 6         29 $container = $self->{context}->session_object($container);
183              
184 6         15 foreach $attrib (@$absorbable_attribs) {
185 12 50       30 if (!defined $self->{$attrib}) { # incorporate if not set yet
186 12         37 $self->{$attrib} = $container->{$attrib};
187             }
188             }
189             }
190 6 50       28 &App::sub_exit() if ($App::trace);
191             }
192              
193             #############################################################################
194             # PUBLIC METHODS
195             #############################################################################
196              
197             #############################################################################
198             # Method: shutdown()
199             #############################################################################
200              
201             =head2 shutdown()
202              
203             * Signature: $self->shutdown();
204             * Throws: App::Exception
205             * Since: 0.01
206              
207             $session_object->shutdown();
208              
209             =cut
210              
211             sub shutdown {
212 0 0   0 1 0 &App::sub_entry if ($App::trace);
213 0         0 my ($self) = @_;
214 0 0       0 &App::sub_exit() if ($App::trace);
215             }
216              
217             =head1 Public Methods:
218              
219             =cut
220              
221             #############################################################################
222             # Method: container()
223             #############################################################################
224              
225             =head2 container()
226              
227             * Signature: $self->container();
228             * Signature: $self->container($name);
229             * Params: $name string
230             * Throws: App::Exception
231             * Since: 0.01
232              
233             $container = $session_object->container();
234              
235             =cut
236              
237             sub container {
238 0 0   0 1 0 &App::sub_entry if ($App::trace);
239 0         0 my ($self, $name) = @_;
240 0   0     0 $name ||= $self->{name};
241 0         0 my ($container);
242 0 0       0 if ($name =~ /^(.+)-[a-zA-Z][a-zA-Z0-9_]*$/) {
243 0         0 $container = $1;
244             }
245             else {
246 0         0 $container = "default";
247             }
248 0 0       0 &App::sub_exit($container) if ($App::trace);
249 0         0 return($container);
250             }
251              
252             #############################################################################
253             # Method: container_attrib()
254             #############################################################################
255              
256             =head2 container_attrib()
257              
258             * Signature: $attrib = $self->container_attrib();
259             * Signature: $attrib = $self->container_attrib($name);
260             * Params: $name string
261             * Returns: $attrib string
262             * Throws: App::Exception
263             * Since: 0.01
264              
265             $attrib = $session_object->container_attrib();
266              
267             =cut
268              
269             sub container_attrib {
270 0 0   0 1 0 &App::sub_entry if ($App::trace);
271 0         0 my ($self, $name) = @_;
272 0   0     0 $name ||= $self->{name};
273 0         0 my ($attrib);
274 0 0       0 if ($name =~ /^.+-([a-zA-Z][a-zA-Z0-9_]*)$/) {
275 0         0 $attrib = $1;
276             }
277             else {
278 0         0 $attrib = $name;
279             }
280 0 0       0 &App::sub_exit($attrib) if ($App::trace);
281 0         0 return($attrib);
282             }
283              
284             #############################################################################
285             # Method: handle_event()
286             #############################################################################
287              
288             =head2 handle_event()
289              
290             * Signature: $handled = $self->handle_event($session_object_name,$event,@args);
291             * Param: $session_object_name string
292             * Param: $event string
293             * Param: @args any
294             * Return: $handled boolean
295             * Throws: App::Exception
296             * Since: 0.01
297              
298             $handled = $session_object->handle_event("app.table.sort","click","up",4,20);
299             $handled = $session_object->handle_event("app.table","sort","down","last_name");
300              
301             =cut
302              
303             sub handle_event {
304 0 0   0 1 0 &App::sub_entry if ($App::trace);
305 0         0 my ($self, $wname, $event, @args) = @_;
306              
307 0         0 my $handled = 0;
308              
309 0 0       0 if ($event eq "noop") { # handle all known events
310 0         0 $handled = 1;
311             }
312             else {
313 0         0 my $name = $self->{name};
314 0         0 my $context = $self->{context};
315 0         0 my $container = "default";
316 0 0       0 if ($name =~ /^(.+)-[a-zA-Z][a-zA-Z0-9_]*$/) {
317 0         0 $container = $1;
318             }
319             else {
320 0         0 my $cname = $context->so_get("default","cname","default");
321 0 0 0     0 if ($cname ne $name && $cname !~ /^$name\./) {
322 0         0 $container = $cname; # container is the current active widget
323             }
324             }
325 0 0       0 if ($container eq "default") {
326 0         0 $context->add_message("Event not handled: {$wname}.$event(@args)");
327 0         0 $handled = 1;
328             }
329             else {
330 0         0 my $w = $context->session_object($container);
331 0         0 $handled = $w->handle_event($wname, $event, @args); # bubble the event to container session_object
332             }
333             }
334              
335 0 0       0 &App::sub_exit($handled) if ($App::trace);
336 0         0 return($handled);
337             }
338              
339              
340             #############################################################################
341             # Method: set_value()
342             #############################################################################
343              
344             =head2 set_value()
345              
346             * Signature: $self->set_value($value);
347             * Param: $value any
348             * Return: void
349             * Throws: App::Exception
350             * Since: 0.01
351              
352             $session_object->set_value("hello");
353             $session_object->set_value(43);
354              
355             =cut
356              
357             sub set_value {
358 0 0   0 1 0 &App::sub_entry if ($App::trace);
359 0         0 my ($self, $value) = @_;
360 0         0 my $name = $self->{name};
361 0 0       0 if ($name =~ /^(.+)\.([a-zA-Z][a-zA-Z0-9_]*)$/) {
362 0         0 $self->{context}->so_set($1, $2, $value);
363             }
364             else {
365 0         0 $self->{context}->so_set("default", $name, $value);
366             }
367 0 0       0 &App::sub_exit() if ($App::trace);
368             }
369              
370             #############################################################################
371             # Method: get_value()
372             #############################################################################
373              
374             =head2 get_value()
375              
376             * Signature: $value = $self->get_value();
377             * Param: void
378             * Return: $value any
379             * Throws: App::Exception
380             * Since: 0.01
381              
382             $value = $session_object->get_value();
383              
384             =cut
385              
386             sub get_value {
387 0 0   0 1 0 &App::sub_entry if ($App::trace);
388 0         0 my ($self, $default, $setdefault) = @_;
389 0         0 my $value = $self->{context}->so_get($self->{name}, "", $default, $setdefault);
390 0 0       0 &App::sub_exit($value) if ($App::trace);
391 0         0 return $value;
392             }
393              
394             #############################################################################
395             # Method: fget_value()
396             #############################################################################
397              
398             =head2 fget_value()
399              
400             * Signature: $formatted_value = $self->fget_value();
401             * Signature: $formatted_value = $self->fget_value($format);
402             * Param: $format string
403             * Return: $formatted_value scalar
404             * Throws: App::Exception
405             * Since: 0.01
406              
407             $formatted_date = $date_session_object->fget_value(); # use default format
408             $formatted_date = $date_session_object->fget_value("%Y-%m-%d"); # supply format
409              
410             =cut
411              
412             sub fget_value {
413 0 0   0 1 0 &App::sub_entry if ($App::trace);
414 0         0 my ($self, $format) = @_;
415 0 0       0 $format = $self->get("format") if (!defined $format);
416 0         0 my ($value);
417 0 0       0 if (! defined $format) {
418 0         0 $value = $self->get_value("");
419             }
420             else {
421 0         0 my $type = $self->get("validate");
422 0         0 $value = $self->get_value("");
423 0 0       0 if ($type) {
424 0         0 $value = App::SessionObject->format($value, $type, $format);
425             }
426             }
427 0 0       0 &App::sub_exit($value) if ($App::trace);
428 0         0 return($value);
429             }
430              
431             #############################################################################
432             # Method: get_values()
433             #############################################################################
434              
435             =head2 get_values()
436              
437             * Signature: $values = $self->get_values();
438             * Signature: $values = $self->get_values($default);
439             * Signature: $values = $self->get_values($default,$setdefault);
440             * Param: $default any
441             * Param: $setdefault boolean
442             * Return: $values []
443             * Throws: App::Exception
444             * Since: 0.01
445              
446             $values = $session_object->get_values();
447              
448             =cut
449              
450             sub get_values {
451 0 0   0 1 0 &App::sub_entry if ($App::trace);
452 0         0 my ($self, $default, $setdefault) = @_;
453 0         0 my $values = $self->get_value($default, $setdefault);
454 0         0 my (@values);
455 0 0       0 if (!defined $values) {
    0          
456 0         0 @values = ();
457             }
458             elsif (ref($values) eq "ARRAY") {
459 0         0 @values = @$values;
460             }
461             else {
462 0         0 @values = ($values);
463             }
464 0 0       0 &App::sub_exit(@values) if ($App::trace);
465 0         0 return (@values);
466             }
467              
468             #############################################################################
469             # Method: set()
470             #############################################################################
471              
472             =head2 set()
473              
474             * Signature: $self->set($attribute,$value);
475             * Param: $attribute string
476             * Param: $value any
477             * Return: void
478             * Throws: App::Exception
479             * Since: 0.01
480              
481             $session_object->set("last_name","Jones");
482              
483             =cut
484              
485             sub set {
486 0 0   0 1 0 &App::sub_entry if ($App::trace);
487 0         0 my ($self, $var, $value) = @_;
488 0         0 $self->{context}->so_set($self->{name}, $var, $value);
489 0 0       0 &App::sub_exit() if ($App::trace);
490             }
491              
492             #############################################################################
493             # Method: get()
494             #############################################################################
495              
496             =head2 get()
497              
498             * Signature: $value = $self->get($attribute);
499             * Signature: $value = $self->get($attribute,$default);
500             * Signature: $value = $self->get($attribute,$default,$setdefault);
501             * Param: $attribut string
502             * Param: $default any
503             * Param: $setdefault boolean
504             * Return: $value any
505             * Throws: App::Exception
506             * Since: 0.01
507              
508             $last_name = $session_object->get("last_name");
509             $is_adult = $session_object->get("adult_ind","Y"); # assume adult
510             $is_adult = $session_object->get("adult_ind","Y",1); # assume adult, remember
511              
512             =cut
513              
514             sub get {
515 0 0   0 1 0 &App::sub_entry if ($App::trace);
516 0         0 my ($self, $var, $default, $setdefault) = @_;
517 0         0 my $value = $self->{context}->so_get($self->{name}, $var, $default, $setdefault);
518 0 0       0 &App::sub_exit($value) if ($App::trace);
519 0         0 $value;
520             }
521              
522             #############################################################################
523             # Method: delete()
524             #############################################################################
525              
526             =head2 delete()
527              
528             * Signature: $self->delete($attribute);
529             * Param: $attribute string
530             * Return: void
531             * Throws: App::Exception
532             * Since: 0.01
533              
534             $session_object->delete("voter_id");
535              
536             =cut
537              
538             sub delete {
539 0 0   0 1 0 &App::sub_entry if ($App::trace);
540 0         0 my ($self, $var) = @_;
541 0         0 my $result = $self->{context}->so_delete($self->{name}, $var);
542 0 0       0 &App::sub_exit($result) if ($App::trace);
543 0         0 $result;
544             }
545              
546             #############################################################################
547             # Method: set_default()
548             #############################################################################
549              
550             =head2 set_default()
551              
552             * Signature: $self->set_default($attribute,$default);
553             * Param: $attribute string
554             * Param: $default any
555             * Return: void
556             * Throws: App::Exception
557             * Since: 0.01
558              
559             $session_object->set_default("adult_ind","Y");
560              
561             =cut
562              
563             sub set_default {
564 0 0   0 1 0 &App::sub_entry if ($App::trace);
565 0         0 my ($self, $var, $default) = @_;
566 0         0 my $value = $self->{context}->so_get($self->{name}, $var, $default, 1);
567 0 0       0 &App::sub_exit($value) if ($App::trace);
568 0         0 $value;
569             }
570              
571             #############################################################################
572             # Method: label()
573             #############################################################################
574              
575             =head2 label()
576              
577             * Signature: $label = $self->label();
578             * Signature: $label = $self->label($attrib);
579             * Signature: $label = $self->label($attrib,$lang);
580             * Param: $session_object_name string
581             * Param: $event string
582             * Param: @args any
583             * Return: $handled boolean
584             * Throws: App::Exception
585             * Since: 0.01
586              
587             print $w->label(); # "Allez!" (if current lang is "fr")
588             print $w->label("name"); # "Jacques" (translation of alternate attribute) (if curr lang is "fr")
589             print $w->label("name","en");# "Jack" (translation of alternate attribute) (override lang is "en")
590             print $w->label("","en"); # "Go!" (default label, overridden lang of "en")
591             print $w->label("","en_ca"); # "Go! eh?" (default label, overridden lang of "en_ca")
592              
593             =cut
594              
595             sub label {
596 0 0   0 1 0 &App::sub_entry if ($App::trace);
597 0         0 my ($self, $attrib, $lang) = @_;
598 0         0 my ($label);
599             #print "label($attrib, $lang) [$self]\n";
600 0 0 0     0 $attrib = "label" if (!$attrib && $self->{label});
601 0 0 0     0 $attrib = "name" if (!$attrib && $self->{name});
602 0 0       0 $lang = $self->{lang} if (!$lang);
603              
604 0         0 $label = $self->{"${attrib}__${lang}"};
605 0 0       0 return $label if (defined $label);
606              
607 0         0 $label = $self->{$attrib};
608 0 0       0 $label = $self->translate($label,$lang) if ($lang);
609 0         0 $self->{"${attrib}__${lang}"} = $label; # cache it for later use
610             #print "label($attrib, $lang) => $label\n";
611 0 0       0 &App::sub_exit($label) if ($App::trace);
612 0         0 return $label;
613             }
614              
615             #############################################################################
616             # Method: values_labels()
617             #############################################################################
618              
619             =head2 values_labels()
620              
621             * Signature: ($values, $labels) = $self->values_labels();
622             * Param: void
623             * Return: $values []
624             * Return: $labels {}
625             * Throws: App::Exception
626             * Since: 0.01
627              
628             ($values, $labels) = $gender_session_object->values_labels();
629             # $values = [ "M", "F" ];
630             # $labels = { "M" => "Male", "F" => "Female" };
631              
632             =cut
633              
634             sub values_labels {
635 0 0   0 1 0 &App::sub_entry if ($App::trace);
636 0         0 my ($self) = @_;
637 0         0 my ($domain, $values, $labels);
638              
639 0 0 0     0 $self->{context}->dbgprint("SessionObject->values_labels()")
640             if ($App::DEBUG && $self->{context}->dbg(1));
641              
642 0         0 $domain = $self->get("domain");
643 0         0 $values = $self->get("values");
644 0 0 0     0 if (defined $values) {
    0          
645 0         0 $labels = $self->labels();
646             }
647             elsif (defined $domain && $domain ne "") {
648              
649 0 0 0     0 $self->{context}->dbgprint("SessionObject->values_labels(): domain=$domain")
650             if ($App::DEBUG && $self->{context}->dbg(1));
651              
652 0         0 ($values, $labels) = $self->{context}->value_domain($domain)->values_labels();
653             }
654 0 0       0 $values = [] if (! defined $values);
655 0 0       0 $labels = {} if (! defined $labels);
656 0 0       0 &App::sub_exit($values, $labels) if ($App::trace);
657 0         0 ($values, $labels);
658             }
659              
660             #############################################################################
661             # Method: labels()
662             #############################################################################
663              
664             =head2 labels()
665              
666             * Signature: $labels = $self->labels();
667             * Signature: $labels = $self->labels($attribute);
668             * Signature: $labels = $self->labels($attribute,$lang);
669             * Param: $attribute string
670             * Param: $lang string
671             * Return: $labels {}
672             * Throws: App::Exception
673             * Since: 0.01
674              
675             $labels = $w->labels();
676             $labels = $w->labels("names");
677             $labels = $w->labels("","en"); # English
678             $labels = $w->labels("","en_ca"); # Canadian English
679              
680             =cut
681              
682             sub labels {
683 0 0   0 1 0 &App::sub_entry if ($App::trace);
684 0         0 my ($self, $attrib, $lang) = @_;
685 0         0 my ($labels, $langlabels, $key);
686 0 0 0     0 $attrib = "labels" if (!defined $attrib || $attrib eq ""); #"labels" is the default attribute to translate
687 0         0 $langlabels = $self->{"lang_${attrib}"};
688 0 0       0 return $langlabels if (defined $langlabels);
689 0         0 $labels = $self->get("labels");
690 0 0 0     0 if (defined $lang && $lang ne "") {
691 0         0 foreach $key (keys %$labels) {
692 0         0 $langlabels->{$key} = $self->translate($labels->{$key},$lang);
693             }
694             }
695             else {
696 0         0 $lang = $self->get("lang");
697 0         0 foreach $key (keys %$labels) {
698 0         0 $langlabels->{$key} = $self->translate($labels->{$key},$lang);
699             }
700 0         0 $self->{"lang_${attrib}"} = $langlabels; # cache it for later use
701             }
702 0 0       0 &App::sub_exit($langlabels) if ($App::trace);
703 0         0 return $langlabels;
704             }
705              
706             #############################################################################
707             # Method: print()
708             #############################################################################
709              
710             =head2 print()
711              
712             * Signature: $self->print();
713             * Param: void
714             * Return: void
715             * Throws: App::Exception
716             * Since: 0.01
717              
718             $w->print();
719              
720             =cut
721              
722             sub print {
723 0 0   0 1 0 &App::sub_entry if ($App::trace);
724 0         0 my $self = shift;
725 0         0 print $self->dump();
726 0 0       0 &App::sub_exit() if ($App::trace);
727             }
728              
729             #############################################################################
730             # PUBLIC STATIC METHODS
731             #############################################################################
732              
733             =head1 Public Static Methods:
734              
735             =cut
736              
737             #############################################################################
738             # Method: format()
739             #############################################################################
740              
741             =head2 format()
742              
743             * Signature: $formatted_value = $self->format($value, $type, $format);
744             * Param: $value scalar
745             * Param: $type string
746             * Param: $format string
747             * Return: $formatted_value string
748             * Throws: App::Exception
749             * Since: 0.01
750              
751             $formatted_value = $session_object->format("20020127","date","%Y-%m-%d");
752             $formatted_value = $session_object->format("27-Jan-02","date","%Y-%m-%d");
753             $formatted_value = $session_object->format("01/27/2002","date","%Y-%m-%d");
754             $formatted_value = App::SessionObject->format("01/27/2002","date","%Y-%m-%d");
755              
756             A static method.
757              
758             =cut
759              
760             sub format {
761 0     0 1 0 my ($self, $value, $type, $format) = @_;
762 0 0 0     0 return "" if (!defined $value || $value eq "");
763 0 0       0 if ($type eq "date") {
764 0 0       0 if ($value =~ /^([0-9]{4})([0-9]{2})([0-9]{2})$/) {
765 0         0 $value = "$1-$2-$3"; # time2str doesn't get YYYYMMDD
766             }
767 0 0       0 return "" if ($value eq "0000-00-00");
768 0         0 return time2str($format, str2time($value));
769             }
770             }
771              
772             #############################################################################
773             # Method: translate()
774             #############################################################################
775              
776             =head2 translate()
777              
778             * Signature: $translated_label = $session_object->translate($label, $lang);
779             * Param: $label string
780             * Param: $lang string
781             * Return: $translated_label string
782             * Throws: App::Exception
783             * Since: 0.01
784              
785             $translated_label = $session_object->translate($label, $lang);
786             print $w->translate("Hello","fr"); # "Bonjour"
787             print $w->translate("Hello","fr_ca"); # "Bonjour, eh" (french canadian)
788              
789             Translates the label into the desired language based on the dictionary
790             which is current in the session_object at the time.
791             This dictionary is usually a reference to a global dictionary
792             which is absorbed from the container session_object.
793              
794             =cut
795              
796             sub translate {
797 0 0   0 1 0 &App::sub_entry if ($App::trace);
798 0         0 my ($self, $label, $lang) = @_;
799              
800             #print "translate($label, $lang)\n";
801 0   0     0 my $trans_label = $label || "";
802 0 0       0 if (!$label) {
803             # do nothing (reply with blank)
804             }
805             else {
806 0 0       0 $lang = $self->{lang} if (!$lang);
807 0         0 my $context = $self->{context};
808 0         0 my $dict = $context->so_get("dict");
809 0 0 0     0 if (!$lang || !$dict) {
810             # do nothing (return $label without translation)
811             }
812             else {
813 0         0 $trans_label = $dict->{$lang}{$label};
814 0 0       0 if (!defined $trans_label) {
815 0         0 my $base_lang = $lang;
816 0         0 $base_lang =~ s/_.*$//; # trim the trailing modifier (en_us => en)
817 0 0       0 $trans_label = $dict->{$base_lang}{$label} if ($base_lang ne $lang);
818             }
819 0 0       0 $trans_label = $dict->{default}{$label} if (!defined $trans_label);
820 0 0       0 $trans_label = $label if (!$trans_label);
821             }
822             }
823              
824 0 0       0 &App::sub_exit($trans_label) if ($App::trace);
825 0         0 return $trans_label;
826             }
827              
828             #############################################################################
829             # PROTECTED METHODS
830             #############################################################################
831              
832             =head1 Protected Methods:
833              
834             =cut
835              
836             #############################################################################
837             # Method: service_type()
838             #############################################################################
839              
840             =head2 service_type()
841              
842             Returns 'SessionObject';
843              
844             * Signature: $service_type = App::SessionObject->service_type();
845             * Param: void
846             * Return: $service_type string
847             * Since: 0.01
848              
849             $service_type = $session_object->service_type();
850              
851             =cut
852              
853             sub service_type () { 'SessionObject'; }
854              
855             #############################################################################
856             # Method: absorbable_attribs()
857             #############################################################################
858              
859             =head2 absorbable_attribs()
860              
861             Returns a list of attributes which a service of this type would like to
862             absorb from its container service.
863             This is a *static* method.
864             It doesn't require an instance of the class to call it.
865              
866             * Signature: $attribs = App::Service->absorbable_attribs()
867             * Param: void
868             * Return: $attribs []
869             * Throws: App::Exception
870             * Since: 0.01
871              
872             $attribs = $session_object->absorbable_attribs();
873             @attribs = @{$session_object->absorbable_attribs()};
874              
875             =cut
876              
877             sub absorbable_attribs {
878             # for the general session_object, there are only a few universal absorbable attributes
879 6     6 1 19 [ "lang", "dict" ];
880             }
881              
882             =head1 ACKNOWLEDGEMENTS
883              
884             * Author: Stephen Adkins
885             * License: This is free software. It is licensed under the same terms as Perl itself.
886              
887             =head1 SEE ALSO
888              
889             L|App::Context>,
890             L|App::Service>
891              
892             =cut
893              
894             1;
895