File Coverage

blib/lib/Data/Startup.pm
Criterion Covered Total %
statement 32 71 45.0
branch 6 30 20.0
condition 0 3 0.0
subroutine 9 10 90.0
pod 3 3 100.0
total 50 117 42.7


line stmt bran cond sub pod time code
1             #!perl
2             #
3             # The copyright notice and plain old documentation (POD)
4             # are at the end of this file.
5             #
6             package Data::Startup;
7            
8 1     1   26875 use strict;
  1         3  
  1         55  
9 1     1   24 use 5.001;
  1         5  
  1         107  
10 1     1   6 use warnings;
  1         18  
  1         37  
11 1     1   6 use warnings::register;
  1         2  
  1         158  
12 1     1   6 use attributes;
  1         2  
  1         16  
13            
14 1     1   53 use vars qw( $VERSION $DATE $FILE);
  1         2  
  1         96  
15             $VERSION = '0.08';
16             $DATE = '2004/05/27';
17             $FILE = __FILE__;
18            
19 1     1   6 use vars qw(@ISA @EXPORT_OK);
  1         2  
  1         1007  
20             require Exporter;
21             @ISA=('Exporter');
22             @EXPORT_OK = qw(config override);
23            
24             #######
25             # Object used to set default, startup, options values.
26             #
27             sub new
28             {
29 2     2 1 32028 my $class = shift;
30 2 50       12 $class = ref($class) ? ref($class) : $class;
31            
32             #########
33             # Create a new hash in hopes of not to
34             # mangle, which may be a reference outside,
35             # inputs to this subroutine.
36             #
37 2         5 my %startup_options;
38 2         7 my $ref = ref($_[0]);
39 2 50       10 $ref = attributes::reftype($_[0]) if($ref);
40 2 50       10 if($ref eq 'HASH') {
    50          
41 0         0 %startup_options = %{$_[0]};
  0         0  
42 0         0 shift;
43             }
44             elsif($ref eq 'ARRAY') {
45 0         0 %startup_options = @{$_[0]};
  0         0  
46 0         0 shift;
47             }
48             else {
49 2         18 %startup_options = @_;
50             }
51            
52 2         15 bless \%startup_options,$class;
53             }
54            
55            
56             ######
57             # Replace the current values in $self hash
58             #
59             sub config
60             {
61 0     0 1 0 my $self = shift;
62 0         0 my @return;
63            
64             #########
65             # For empty input return the sorted
66             # key, value pairs for all the options
67             #
68 0 0       0 unless(@_) {
69 0         0 foreach (sort keys %$self) {
70 0         0 push @return, $_, $self->{$_};
71             }
72 0         0 return @return;
73             }
74            
75             ######
76             # Move hash reference into $options_override,
77             # array references and \@_ into $array
78             #
79 0         0 my $options_override = {};
80 0         0 my $array = [];
81 0         0 my $ref = ref($_[0]);
82 0 0       0 $ref = attributes::reftype($_[0]) if($ref);
83 0 0       0 if($ref) {
84 0 0       0 if($ref eq 'HASH') {
    0          
85 0         0 $options_override = $_[0];
86             }
87             elsif($ref eq 'ARRAY') {
88 0         0 $array = $_[0];
89             }
90             }
91             else {
92 0         0 $array = \@_;
93             }
94            
95             ######
96             # Move $array into %options_override
97             # For problem arrays with odd members greater
98             # than one, return an undef.
99             #
100             # Arrays with one member, the key value using
101             # the single member as a key.
102             #
103 0 0 0     0 if(@$array == 1) {
  0 0       0  
104 0         0 return ($array->[0], $self->{$array->[0]});
105             }
106             elsif(@$array && ${$array}[0]) {
107 0 0       0 if(@$array % 2 == 0) {
108 0         0 my %hash = @$array;
109 0         0 $options_override = \%hash;
110             }
111             else {
112 0         0 return undef;
113             }
114             }
115            
116             ######
117             # Override the $self options, returning
118             # the sorted key, value of the replaced options
119             #
120 0         0 foreach (sort keys %$options_override) {
121 0         0 push @return, $_, $self->{$_};
122 0         0 $self->{$_} = $options_override->{$_};
123             }
124 0         0 @return;
125             }
126            
127            
128             #######
129             # Override the options in a default object and create
130             # a new object with the override options, perserving
131             # the default object.
132             #
133             sub override
134             {
135 1     1 1 8 my $self = shift;
136 1 50       5 return bless {},'Data::Startup' unless ref($self);
137            
138             #####
139             # Return if no override values
140             #
141 1 50       7 return $self unless (@_);
142            
143             #########
144             # Create a duplicate object keeping the
145             # the default object intact.
146 0           my %options = %$self;
147            
148             #####
149             # Process options hash
150             #
151 0 0         if(ref($self) eq 'HASH') {
152 0           Data::Startup::config(\%options,@_);
153 0           return \%options;
154             }
155            
156             #####
157             # Process a object with hash underlying data
158             #
159 0           $self = bless \%options,ref($self);
160            
161             ##############
162             # Do not want to gyrate around to any other
163             # config in @ISA. Go directly to the one in this
164             # program module.
165             #
166 0           $self->Data::Startup::config(@_);
167 0           $self
168            
169             }
170            
171             =head1 NAME
172            
173             Data::Startup - startup options class, override, config methods
174            
175             =head1 SYNOPSIS
176            
177             ######
178             # Subroutine interface
179             #
180             use Data::Startup qw(config override);
181            
182             $options = override(\%default_options, @option_list );
183             $options = override(\%default_options, \@option_list );
184             $options = override(\%default_options, \%option_list );
185            
186             @options_list = config(\%options );
187            
188             ($key, $old_value) = config(\%options, $key);
189             ($key, $old_value) = config(\%options, $key => $new_value );
190             ($key, $old_value) = config(\%options, $key => $new_value );
191            
192             @old_options_list = config(\%options, @option_list);
193             @old_options_list = config(\%options, \@option_list);
194             @old_options_list = config(\%options, \%option_list);
195            
196             ######
197             # Object interface
198             #
199             use Data::Startup
200            
201             $startup_options = $class->Data::Startup::new( @option_list );
202             $startup_options = $class->Data::Startup::new( \@option_list );
203             $startup_options = $class->Data::Startup::new( \%option_list );
204            
205             $options = $startup_options->override( @option_list );
206             $options = $startup_options->override( \@option_list );
207             $options = $startup_options->override( \%option_list );
208            
209             @options_list = $options->config( );
210            
211             ($key, $old_value) = $options->config($key);
212             ($key, $old_value) = $options->config($key => $new_value );
213             ($key, $old_value) = $options->config($key => $new_value );
214            
215             @old_options_list = $options->config(@option_list);
216             @old_options_list = $options->config(\@option_list);
217             @old_options_list = $options->config(\%option_list);
218            
219             # Note: May use [@option_list] instead of \@option_list
220             # and {@option_list} instead of \%option_list
221            
222             =head1 DESCRIPTION
223            
224             Many times there is a group of subroutines that can be tailored by
225             different situations with a few, say global variables.
226             However, global variables pollute namespaces, become mangled
227             when the functions are multi-threaded and probably have many
228             other faults that it is not worth the time discovering.
229            
230             As well documented in literature, object oriented programming do not have
231             these faults.
232             This program module class of objects provide the objectized options
233             for a group of subroutines or encapsulated options by using
234             the methods directly as in an option object.
235            
236             The C class provides a way to input options
237             in very liberal manner of either
238            
239             =over 4
240            
241             =item *
242            
243             arrays, reference to an array, or reference to hash to a
244            
245             =item *
246            
247             reference to an array or reference to a hash
248            
249             =item *
250            
251             reference to a hash
252            
253             =item *
254            
255             referene to an array
256            
257             =item *
258            
259             many other combos
260            
261             =back
262            
263             without having to cut and paste specialize, tailored
264             code into each subroutine/method.
265            
266             Some of the possiblities follows.
267            
268             A subroutine may be utilize either as a subroutine or a method
269             of a object by processing the first argument of @_ by the
270             following:
271            
272             sub my_suroutine
273             {
274             shift if UNIVERSAL::isa($_[0],__PACKAGE__);
275            
276             # ....
277            
278             }
279            
280             The C class may be used to provide various
281             options syntax for a dual methods/subroutines as follows:
282            
283             my $default_options = new( @default_options_list);
284            
285             # SYNTAX: my_subroutine1($arg1 .. $argn, @options)
286             # my_subroutine1($arg1 .. $argn, \@options)
287             # my_subroutine1($arg1 .. $argn, \%options)
288             #
289            
290            
291             sub my_subroutine1
292             {
293             shift if UNIVERSAL::isa($_[0],__PACKAGE__);
294             $default_options = Data::Startup->new() unless $default_options;
295             my ($arg1 .. $argn, @options) = @_
296             my $options = $default_options->override(@options);
297            
298             # ....
299             }
300            
301             # SYNTAX: my_subroutine2(\@options, @args)
302             # my_subroutine2(\%options, @args)
303             #
304             # !ref($args[0])
305            
306             sub my_subroutine2
307             {
308             shift if UNIVERSAL::isa($_[0],__PACKAGE__);
309             $default_options = Data::Startup->new() unless $default_options;
310             my $options = $default_options->override(shift @_) if ref($_[0]);
311            
312             # ....
313             }
314            
315             # SYNTAX: my_subroutine3(\%options, @args)
316             #
317             # ref($args[0]) ne 'HASH'
318            
319             sub my_subroutine3
320             {
321             shift if UNIVERSAL::isa($_[0],__PACKAGE__);
322             $default_options = Data::Startup->new() unless $default_options;
323             my $options = $default_options->override(shift @_) if ref($_[0] eq 'HASH');
324             my (@args) = @_;
325            
326             # ....
327             }
328            
329             If program module does not require program module wide global
330             default options, than still use C to provide
331             liberal options syntax as follows
332            
333             # SYNTAX: my_subroutine1($arg1 .. $argn, @options)
334             # my_subroutine1($arg1 .. $argn, \@options)
335             # my_subroutine1($arg1 .. $argn, \%options)
336             #
337            
338             sub my_subroutine4
339             {
340             shift if UNIVERSAL::isa($_[0],__PACKAGE__);
341             my ($arg1 .. $argn, @options) = @_
342             my $options = new Data::Startup(@options);
343            
344             # ....
345             }
346            
347             This technique may be extended to many more different subroutine with
348             a similar style syntax.
349            
350             The C class may be used
351             may also be used to create objects off a base C<$default_object> as follows:
352            
353             use Data_Startup;
354             unshift @ISA,'Data_Startup'; # first among classes
355             use vars qw($default_object);
356             $default_object = new Data::Startup( @default_list);
357            
358             sub new
359             {
360             $default_options->override( @_ );
361            
362             }
363            
364             my $object = new my_package;
365            
366             my @old_options = object->config( @_ );
367             my @old_default_options = $my_package::$default_object->config( @_ );
368            
369             sub method
370             {
371             $self = shift;
372             $value1 = $self->{$key1};
373            
374             }
375            
376             And then there are the hybrid subroutine, class syntax and
377             probably some other possibilies that are not readily apparent.
378            
379             =head1 METHODS
380            
381             =head2 new
382            
383             The C method c the input C<@option_list> creating
384             a default options hash object.
385            
386             =head2 config
387            
388             The C method reads and writes individual key,value pairs
389             or groups of key,value pairs in the C<$option> object.
390            
391             The method response with no inputs with all the C<$key,$value>
392             pairs in C<$options>; a single C<$key> input with the C<$key,$value>
393             for that C<$key>; and, a group of C<$key, $value> pairs, C<@option_list>
394             by replacing all the C<$option> C<$key> in the group by the paired <$value> returning
395             the C<@old_options_list> of old C<$key,$value> pairs.
396             The C method does not care if the C<@option_list> is an
397             array, a reference to an array or a reference to a hash.
398            
399             =head2 override
400            
401             The C method takes a default options object, C<$startup_options>,
402             creates a new duplicate object, C<$options>, keeping C<$startup_options>
403             intact, and replaces selected optioins in C<$options> with override
404             values, C<@option_list>.
405            
406             =head1 REQUIREMENTS
407            
408             Coming.
409            
410             =head1 DEMONSTRATION
411            
412             #########
413             # perl Startup.d
414             ###
415            
416             ~~~~~~ Demonstration overview ~~~~~
417            
418             The results from executing the Perl Code
419             follow on the next lines as comments. For example,
420            
421             2 + 2
422             # 4
423            
424             ~~~~~~ The demonstration follows ~~~~~
425            
426             use File::Package;
427             my $uut = 'Data::Startup';
428            
429             my ($result,@result); # provide scalar and array context
430             my ($default_options,$options) = ('$default_options','$options');
431            
432             ##################
433             # create a Data::Startup default options
434             #
435            
436             ($default_options = new $uut(
437             perl_secs_numbers => 'multicell',
438             type => 'ascii',
439             indent => '',
440             'Data::SecsPack' => {}
441             ))
442            
443             # bless( {
444             # 'perl_secs_numbers' => 'multicell',
445             # 'Data::SecsPack' => {},
446             # 'type' => 'ascii',
447             # 'indent' => ''
448             # }, 'Data::Startup' )
449             #
450            
451             ##################
452             # read perl_secs_numbers default option
453             #
454            
455             [$default_options->config('perl_secs_numbers')]
456            
457             # [
458             # 'perl_secs_numbers',
459             # 'multicell'
460             # ]
461             #
462            
463             ##################
464             # write perl_secs_numbers default option
465             #
466            
467             [$default_options->config(perl_secs_numbers => 'strict')]
468            
469             # [
470             # 'perl_secs_numbers',
471             # 'multicell'
472             # ]
473             #
474            
475             ##################
476             # restore perl_secs_numbers default option
477             #
478            
479             [$default_options->config(perl_secs_numbers => 'multicell')]
480            
481             # [
482             # 'perl_secs_numbers',
483             # 'strict'
484             # ]
485             #
486            
487             ##################
488             # create options copy of default options
489             #
490            
491             $options = $default_options->override(type => 'binary')
492            
493             # bless( {
494             # 'perl_secs_numbers' => 'multicell',
495             # 'Data::SecsPack' => {},
496             # 'type' => 'binary',
497             # 'indent' => ''
498             # }, 'Data::Startup' )
499             #
500            
501             ##################
502             # verify default options unchanged
503             #
504            
505             $default_options
506            
507             # bless( {
508             # 'perl_secs_numbers' => 'multicell',
509             # 'Data::SecsPack' => {},
510             # 'type' => 'ascii',
511             # 'indent' => ''
512             # }, 'Data::Startup' )
513             #
514            
515             ##################
516             # array reference option config
517             #
518            
519             [@result = $options->config([perl_secs_numbers => 'strict'])]
520            
521             # [
522             # 'perl_secs_numbers',
523             # 'multicell'
524             # ]
525             #
526            
527             ##################
528             # array reference option config
529             #
530            
531             $options
532            
533             # bless( {
534             # 'perl_secs_numbers' => 'strict',
535             # 'Data::SecsPack' => {},
536             # 'type' => 'binary',
537             # 'indent' => ''
538             # }, 'Data::Startup' )
539             #
540            
541             ##################
542             # hash reference option config
543             #
544            
545             [@result = $options->config({'Data::SecsPack'=> {decimal_fraction_digits => 30} })]
546            
547             # [
548             # 'Data::SecsPack',
549             # {}
550             # ]
551             #
552            
553             ##################
554             # hash reference option config
555             #
556            
557             $options
558            
559             # bless( {
560             # 'perl_secs_numbers' => 'strict',
561             # 'Data::SecsPack' => {
562             # 'decimal_fraction_digits' => 30
563             # },
564             # 'type' => 'binary',
565             # 'indent' => ''
566             # }, 'Data::Startup' )
567             #
568            
569             ##################
570             # verify default options still unchanged
571             #
572            
573             $default_options
574            
575             # bless( {
576             # 'perl_secs_numbers' => 'multicell',
577             # 'Data::SecsPack' => {},
578             # 'type' => 'ascii',
579             # 'indent' => ''
580             # }, 'Data::Startup' )
581             #
582            
583             ##################
584             # create a hash default options
585             #
586            
587             my %default_hash = (
588             perl_secs_numbers => 'multicell',
589             type => 'ascii',
590             indent => '',
591             'Data::SecsPack' => {}
592             );
593             $default_options = \%default_hash
594            
595             # {
596             # 'perl_secs_numbers' => 'multicell',
597             # 'Data::SecsPack' => {},
598             # 'type' => 'ascii',
599             # 'indent' => ''
600             # }
601             #
602            
603             ##################
604             # override default_hash with an option array
605             #
606            
607             Data::Startup::override($default_options, type => 'binary')
608            
609             # {
610             # 'perl_secs_numbers' => 'multicell',
611             # 'Data::SecsPack' => {},
612             # 'type' => 'binary',
613             # 'indent' => ''
614             # }
615             #
616            
617             ##################
618             # override default_hash with a reference to a hash
619             #
620            
621             Data::Startup::override($default_options, {'Data::SecsPack'=> {decimal_fraction_digits => 30}})
622            
623             # {
624             # 'perl_secs_numbers' => 'multicell',
625             # 'Data::SecsPack' => {
626             # 'decimal_fraction_digits' => 30
627             # },
628             # 'type' => 'ascii',
629             # 'indent' => ''
630             # }
631             #
632            
633             ##################
634             # override default_hash with a reference to an array
635             #
636            
637             Data::Startup::override($default_options, [perl_secs_numbers => 'strict'])
638            
639             # {
640             # 'perl_secs_numbers' => 'strict',
641             # 'Data::SecsPack' => {},
642             # 'type' => 'ascii',
643             # 'indent' => ''
644             # }
645             #
646            
647             ##################
648             # return from config default_hash with a reference to an array
649             #
650            
651             [@result = Data::Startup::config($default_options, [perl_secs_numbers => 'strict'])]
652            
653             # [
654             # 'perl_secs_numbers',
655             # 'multicell'
656             # ]
657             #
658            
659             ##################
660             # default_hash from config default_hash with a reference to an array
661             #
662            
663             $default_options
664            
665             # {
666             # 'perl_secs_numbers' => 'strict',
667             # 'Data::SecsPack' => {},
668             # 'type' => 'ascii',
669             # 'indent' => ''
670             # }
671             #
672            
673             =head1 QUALITY ASSURANCE
674            
675             Running the test script C verifies
676             the requirements for this module.
677             The C cover script for L
678             automatically generated the
679             C test script, C demo script,
680             and C program module POD,
681             from the C program module contents.
682             The C cover script automatically ran the
683             C demo script and inserted the results
684             into the 'DEMONSTRATION' section above.
685             The C program module
686             is in the distribution file
687             F.
688            
689             =head1 NOTES
690            
691             =head2 Author
692            
693             The holder of the copyright and maintainer is
694            
695             Esupport@SoftwareDiamonds.comE
696            
697             =head2 Copyright Notice
698            
699             Copyrighted (c) 2002 Software Diamonds
700            
701             All Rights Reserved
702            
703             =head2 Binding Requirements Notice
704            
705             Binding requirements are indexed with the
706             pharse 'shall[dd]' where dd is an unique number
707             for each header section.
708             This conforms to standard federal
709             government practices, L.
710             In accordance with the License, Software Diamonds
711             is not liable for any requirement, binding or otherwise.
712            
713             =head2 License
714            
715             Software Diamonds permits the redistribution
716             and use in source and binary forms, with or
717             without modification, provided that the
718             following conditions are met:
719            
720             =over 4
721            
722             =item 1
723            
724             Redistributions of source code must retain
725             the above copyright notice, this list of
726             conditions and the following disclaimer.
727            
728             =item 2
729            
730             Redistributions in binary form must
731             reproduce the above copyright notice,
732             this list of conditions and the following
733             disclaimer in the documentation and/or
734             other materials provided with the
735             distribution.
736            
737             =item 3
738            
739             Commercial installation of the binary or source
740             must visually present to the installer
741             the above copyright notice,
742             this list of conditions intact,
743             that the original source is available
744             at http://softwarediamonds.com
745             and provide means
746             for the installer to actively accept
747             the list of conditions;
748             otherwise, a license fee must be paid to
749             Softwareware Diamonds.
750            
751            
752             =back
753            
754             SOFTWARE DIAMONDS, http://www.softwarediamonds.com,
755             PROVIDES THIS SOFTWARE
756             'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
757             INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
758             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
759             A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
760             SHALL SOFTWARE DIAMONDS BE LIABLE FOR ANY DIRECT,
761             INDIRECT, INCIDENTAL, SPECIAL,EXEMPLARY, OR
762             CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
763             TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
764             LOSS OF USE,DATA, OR PROFITS; OR BUSINESS
765             INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
766             OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
767             OR TORT (INCLUDING USE OF THIS SOFTWARE, EVEN IF
768             ADVISED OF NEGLIGENCE OR OTHERWISE) ARISING IN
769             ANY WAY OUT OF THE POSSIBILITY OF SUCH DAMAGE.
770            
771             =head1 SEE ALSO
772            
773             =over 4
774            
775             =item L
776            
777             =item L
778            
779             =back
780            
781             =cut
782            
783             ### end of script ######