File Coverage

blib/lib/Module/Starter/Plugin/CGIApp.pm
Criterion Covered Total %
statement 286 298 95.9
branch 27 48 56.2
condition 5 14 35.7
subroutine 39 39 100.0
pod 25 25 100.0
total 382 424 90.0


line stmt bran cond sub pod time code
1              
2             =head1 NAME
3              
4             Module::Starter::Plugin::CGIApp - template based module starter for CGI apps.
5              
6             =head1 SYNOPSIS
7              
8             use Module::Starter qw(
9             Module::Starter::Plugin::CGIApp
10             );
11              
12             Module::Starter->create_distro(%args);
13              
14             =head1 ABSTRACT
15              
16             This is a plugin for L that builds you a skeleton
17             L module with all the extra files needed to package it for
18             CPAN. You can customize the output using L.
19              
20             =cut
21              
22             package Module::Starter::Plugin::CGIApp;
23              
24 4     4   141720 use base 'Module::Starter::Simple';
  4         11  
  4         4627  
25 4     4   72667 use warnings;
  4         9  
  4         124  
26 4     4   22 use strict;
  4         281  
  4         150  
27 4     4   25 use Carp qw( croak );
  4         8  
  4         262  
28 4     4   919 use English qw( -no_match_vars );
  4         5285  
  4         48  
29 4     4   1904 use File::Basename;
  4         9  
  4         453  
30 4     4   29 use File::Path qw( mkpath );
  4         8  
  4         185  
31 4     4   23 use File::Spec ();
  4         5  
  4         63  
32 4     4   20 use Module::Starter::BuilderSet;
  4         7  
  4         87  
33 4     4   7066 use HTML::Template;
  4         96588  
  4         15474  
34              
35             =head1 VERSION
36              
37             This document describes version 0.41
38              
39             =cut
40              
41             our $VERSION = '0.41';
42              
43             =head1 DESCRIPTION
44              
45             This module subclasses L and
46             includes functionality similar to L.
47             This document only describes the methods which are overriden from those modules or are new.
48              
49             Only developers looking to extend this module need to read this. If you just
50             want to use L, read the docs for
51             L or L instead.
52              
53             =head1 METHODS
54              
55             =head2 new ( %args )
56              
57             This method calls the C supermethod from
58             L and then
59             initializes the template store. (See C.)
60              
61             =cut
62              
63             sub new {
64 3     3 1 48 my ( $proto, %opts ) = @_;
65 3   33     118 my $class = ref $proto || $proto;
66              
67 3         116 my $self = $class->SUPER::new(%opts);
68 3         122 $self->{templates} = { $self->templates };
69              
70 3         25 return bless $self => $class;
71             }
72              
73             =head2 create_distro ( %args )
74              
75             This method works as advertised in L.
76              
77             =cut
78              
79             sub create_distro {
80 3     3 1 160376 my ( $either, %opts ) = @_;
81 3 50       133 ( ref $either ) or $either = $either->new(%opts);
82 3         12 my $self = $either;
83              
84             # Supposedly the *-starter scripts can handle multiple --builder options
85             # but this doesn't work (and IMO doesn't make sense anyway.) So in the
86             # case multiple builders were specified, we just pick the first one.
87 3 50       17 if ( ref $self->{builder} eq 'ARRAY' ) {
88 0         0 $self->{builder} = $self->{builder}->[0];
89             }
90              
91 3         17 my @modules;
92 3         10 foreach my $arg ( @{ $self->{modules} } ) {
  3         24  
93 6         219 push @modules, ( split /[,]/msx, $arg );
94             }
95 3 50       148 if ( !@modules ) {
96 0         0 croak "No modules specified.\n";
97             }
98 3         80 for (@modules) {
99 6 50       182 if ( !/\A [[:alpha:]_] \w* (?: [:] [:] [\w]+ )* \Z /imsx ) {
100 0         0 croak "Invalid module name: $_";
101             }
102             }
103 3         11 $self->{modules} = \@modules;
104              
105 3 50       19 if ( !$self->{author} ) {
106 0         0 croak "Must specify an author\n";
107             }
108 3 50       150 if ( !$self->{email} ) {
109 0         0 croak "Must specify an email address\n";
110             }
111 3         29 ( $self->{email_obfuscated} = $self->{email} ) =~ s/@/ at /msx;
112              
113 3   50     40 $self->{license} ||= 'perl';
114              
115 3         15 $self->{main_module} = $self->{modules}->[0];
116 3 50       14 if ( !$self->{distro} ) {
117 0         0 $self->{distro} = $self->{main_module};
118 0         0 $self->{distro} =~ s/::/-/gmsx;
119             }
120              
121 3   33     16 $self->{basedir} = $self->{dir} || $self->{distro};
122 3         56 $self->create_basedir;
123              
124 3         1985 my @files;
125 3         10 push @files, $self->create_modules( @{ $self->{modules} } );
  3         58  
126              
127 3         13 push @files, $self->create_t( @{ $self->{modules} } );
  3         69  
128 3         11 push @files, $self->create_xt( @{ $self->{modules} } );
  3         254  
129 3         38 push @files, $self->create_tmpl();
130 3         60 my %build_results = $self->create_build();
131 3         1182 push @files, @{ $build_results{files} };
  3         12  
132              
133 3         48 push @files, $self->create_Changes;
134 3         3745 push @files, $self->create_LICENSE;
135 3         41 push @files, $self->create_README( $build_results{instructions} );
136 3         1242 push @files, $self->create_MANIFEST_SKIP;
137 3         36 push @files, $self->create_perlcriticrc;
138 3         48 push @files, $self->create_server_pl;
139 3         19 push @files, 'MANIFEST';
140 3     3   59 $self->create_MANIFEST( sub { _create_manifest( $self, @files ) } );
  3         67  
141              
142 3         1507 return;
143             }
144              
145             sub _create_manifest {
146 3     3   92 my ( $self, @files ) = @_;
147              
148 3         82 my $file = File::Spec->catfile( $self->{basedir}, 'MANIFEST' );
149 3 50       236 open my $fh, '>', $file or croak "Can't open file $file: $OS_ERROR\n";
150 3         37 foreach my $file ( sort @files ) {
151 57 50       54 print {$fh} "$file\n" or croak "$OS_ERROR\n";
  57         158  
152             }
153 3 50       197 close $fh or croak "Can't close file $file: $OS_ERROR\n";
154              
155 3         24 return;
156             }
157              
158             =head2 create_LICENSE( )
159              
160             This method creates a C file in the distribution's directory which
161             can hold the distribution's license terms.
162              
163             =cut
164              
165             sub create_LICENSE { ## no critic 'NamingConventions::Capitalization'
166 3     3 1 9 my $self = shift;
167              
168 3         52 my $fname = File::Spec->catfile( $self->{basedir}, 'LICENSE' );
169 3         26 $self->create_file( $fname, $self->LICENSE_guts() );
170 3         862 $self->progress("Created $fname");
171              
172 3         81 return 'LICENSE';
173             }
174              
175             =head2 create_MANIFEST_SKIP( )
176              
177             This method creates a C file in the distribution's directory so
178             that unneeded files can be skipped from inclusion in the distribution.
179              
180             =cut
181              
182             sub create_MANIFEST_SKIP { ## no critic 'NamingConventions::Capitalization'
183 3     3 1 10 my $self = shift;
184              
185 3         206 my $fname = File::Spec->catfile( $self->{basedir}, 'MANIFEST.SKIP' );
186 3         40 $self->create_file( $fname, $self->MANIFEST_SKIP_guts() );
187 3         698 $self->progress("Created $fname");
188              
189 3         29 return 'MANIFEST.SKIP';
190             }
191              
192             =head2 create_modules( @modules )
193              
194             This method will create a starter module file for each module named in
195             I<@modules>. It is only subclassed from L here
196             so we can change the I tmpl_var to be the distro name instead of
197             the module name.
198              
199             =cut
200              
201             sub create_modules {
202 3     3 1 14 my ( $self, @modules ) = @_;
203              
204 3         6 my @files;
205              
206 3         12 my $rtname = lc $self->{distro};
207 3         173 for my $module (@modules) {
208 6         2557 push @files, $self->_create_module( $module, $rtname );
209             }
210              
211 3         2156 return @files;
212             }
213              
214             =head2 create_perlcriticrc( )
215              
216             This method creates a C in the distribution's author test
217             directory so that the behavior of C can be modified.
218              
219             =cut
220              
221             sub create_perlcriticrc {
222 3     3 1 8 my $self = shift;
223              
224 3         13 my @dirparts = ( $self->{basedir}, 'xt' );
225 3         33 my $tdir = File::Spec->catdir(@dirparts);
226 3 50       90 if ( not -d $tdir ) {
227 0         0 mkpath($tdir);
228 0         0 $self->progress("Created $tdir");
229             }
230              
231 3         34 my $fname = File::Spec->catfile( @dirparts, 'perlcriticrc' );
232 3         37 $self->create_file( $fname, $self->perlcriticrc_guts() );
233 3         8152 $self->progress("Created $fname");
234              
235 3         35 return 'xt/perlcriticrc';
236             }
237              
238             =head2 create_server_pl( )
239              
240             This method creates C in the distribution's root directory.
241              
242             =cut
243              
244             sub create_server_pl {
245 3     3 1 7 my $self = shift;
246              
247 3         55 my $fname = File::Spec->catfile( $self->{basedir}, 'server.pl' );
248 3         33 $self->create_file( $fname, $self->server_pl_guts() );
249 3         760 $self->progress("Created $fname");
250              
251 3         24 return 'server.pl';
252             }
253              
254             =head2 create_t( @modules )
255              
256             This method creates a bunch of *.t files. I<@modules> is a list of all modules
257             in the distribution.
258              
259             =cut
260              
261             sub create_t {
262 3     3 1 12 my ( $self, @modules ) = @_;
263              
264 3         41 my %t_files = $self->t_guts(@modules);
265              
266 3         14 my @files = map { $self->_create_t( $_, $t_files{$_} ) } keys %t_files;
  12         12761  
267              
268             # This next part is for the static files dir t/www
269 3         1268 my @dirparts = ( $self->{basedir}, 't', 'www' );
270 3         38 my $twdir = File::Spec->catdir(@dirparts);
271 3 50       115 if ( not -d $twdir ) {
272 3         869 mkpath($twdir);
273 3         28 $self->progress("Created $twdir");
274             }
275 3         65 my $placeholder =
276             File::Spec->catfile( @dirparts, 'PUT.STATIC.CONTENT.HERE' );
277 3         100 $self->create_file( $placeholder, q{ } );
278 3         920 $self->progress("Created $placeholder");
279 3         33 push @files, 't/www/PUT.STATIC.CONTENT.HERE';
280              
281 3         72 return @files;
282             }
283              
284             =head2 create_tmpl( )
285              
286             This method takes all the template files ending in .html (representing
287             L's and installs them into a directory under the distro tree.
288             For instance if the distro was called C, the templates would be
289             installed in C.
290              
291             Note the files will just be copied over not rendered.
292              
293             =cut
294              
295             sub create_tmpl {
296 3     3 1 9 my $self = shift;
297              
298 3         43 return $self->tmpl_guts();
299             }
300              
301             =head2 create_xt( @modules )
302              
303             This method creates a bunch of *.t files for author tests. I<@modules> is a
304             list of all modules in the distribution.
305              
306             =cut
307              
308             sub create_xt {
309 3     3 1 13 my ( $self, @modules ) = @_;
310              
311 3         49 my %xt_files = $self->xt_guts(@modules);
312              
313 3         15 my @files = map { $self->_create_xt( $_, $xt_files{$_} ) } keys %xt_files;
  9         72  
314              
315 3         23 return @files;
316             }
317              
318             sub _create_xt {
319 9     9   18 my ( $self, $filename, $content ) = @_;
320              
321 9         27 my @dirparts = ( $self->{basedir}, 'xt' );
322 9         92 my $xtdir = File::Spec->catdir(@dirparts);
323 9 100       336 if ( not -d $xtdir ) {
324 3         1845 mkpath($xtdir);
325 3         30 $self->progress("Created $xtdir");
326             }
327              
328 9         122 my $fname = File::Spec->catfile( @dirparts, $filename );
329 9         44 $self->create_file( $fname, $content );
330 9         1733 $self->progress("Created $fname");
331              
332 9         91 return "xt/$filename";
333             }
334              
335             =head2 render( $template, \%options )
336              
337             This method is given an L and options and
338             returns the resulting document.
339              
340             Data in the C object which represents a reference to an array
341             @foo is transformed into an array of hashes with one key called
342             C<$foo_item> in order to make it usable in an L C.
343             For example:
344              
345             $data = ['a'. 'b', 'c'];
346              
347             would become:
348              
349             $data = [
350             { data_item => 'a' },
351             { data_item => 'b' },
352             { data_item => 'c' },
353             ];
354            
355             so that in the template you could say:
356              
357            
358            
359            
360            
361             =cut
362              
363             sub render {
364 48     48 1 104 my ( $self, $template, $options ) = @_;
365              
366             # we need a local copy of $options otherwise we get recursion in loops
367             # because of [1]
368 48         75 my %opts = %{$options};
  48         192  
369              
370 48         74 $opts{nummodules} = scalar @{ $self->{modules} };
  48         143  
371 48         194 $opts{year} = $self->_thisyear();
372 48         2002 $opts{license_blurb} = $self->_license_blurb();
373 48         162 $opts{datetime} = scalar localtime;
374 48         1129 $opts{buildscript} =
375             Module::Starter::BuilderSet->new()->file_for_builder( $self->{builder} );
376              
377 48         10027 foreach my $key ( keys %{$self} ) {
  48         476  
378 576 100       1252 next if defined $opts{$key};
379 549         1184 $opts{$key} = $self->{$key};
380             }
381              
382             # [1] HTML::Templates wants loops to be arrays of hashes not plain arrays
383 48         426 foreach my $key ( keys %opts ) {
384 876 100       2440 if ( ref $opts{$key} eq 'ARRAY' ) {
385 90         146 my @temp = ();
386 90         111 for my $option ( @{ $opts{$key} } ) {
  90         188  
387 138         446 push @temp, { "${key}_item" => $option };
388             }
389 90         438 $opts{$key} = [@temp];
390             }
391             }
392 48 50       1076 my $t = HTML::Template->new(
393             die_on_bad_params => 0,
394             scalarref => \$template,
395             ) or croak "Can't create template $template";
396 48         44342 $t->param( \%opts );
397 48         9121 return $t->output;
398             }
399              
400             =head2 templates ( )
401              
402             This method reads in the template files and populates the object's templates
403             attribute. The module template directory is found by checking the
404             C environment variable and then the config option
405             C.
406              
407             =cut
408              
409             sub templates {
410 3     3 1 10 my ($self) = @_;
411 3         14 my %template;
412              
413 3 50 33     80 my $template_dir = ( $ENV{MODULE_TEMPLATE_DIR} || $self->{template_dir} )
414             or croak 'template dir not defined';
415 3 50       74 if ( !-d $template_dir ) {
416 0         0 croak "template dir does not exist: $template_dir";
417             }
418              
419 3         2394 foreach ( glob "$template_dir/*" ) {
420 57         2113 my $basename = basename $_;
421 57 50 33     1246 next if ( not -f $_ ) or ( $basename =~ /\A [.]/msx );
422 57 50       3232 open my $template_file, '<', $_
423             or croak "couldn't open template: $_";
424 57         70 $template{$basename} = do {
425 57         326 local $RS = undef;
426 57         4089 <$template_file>;
427             };
428 57 50       1358 close $template_file or croak "couldn't close template: $_";
429             }
430              
431 3         112 return %template;
432             }
433              
434             =head2 Build_PL_guts($main_module, $main_pm_file)
435              
436             This method is called by L and returns text used to populate
437             Build.PL when the builder is L; I<$main_pm_file>
438             is the filename of the distribution's main module, I<$main_module>.
439              
440             =cut
441              
442             sub Build_PL_guts { ## no critic 'NamingConventions::Capitalization'
443 1     1 1 426 my ( $self, $main_module, $main_pm_file ) = @_;
444 1         2 my %options;
445 1         2 $options{main_module} = $main_module;
446 1         3 $options{main_pm_file} = $main_pm_file;
447              
448 1         3 my $template = $self->{templates}{'Build.PL'};
449 1         4 return $self->render( $template, \%options );
450             }
451              
452             =head2 Changes_guts
453              
454             Implements the creation of a C file.
455              
456             =cut
457              
458             sub Changes_guts { ## no critic 'NamingConventions::Capitalization'
459 3     3 1 74 my $self = shift;
460 3         6 my %options;
461              
462 3         10 my $template = $self->{templates}{Changes};
463 3         15 return $self->render( $template, \%options );
464             }
465              
466             =head2 LICENSE_guts
467              
468             Implements the creation of a C file.
469              
470             =cut
471              
472             sub LICENSE_guts { ## no critic 'NamingConventions::Capitalization'
473 3     3 1 10 my $self = shift;
474 3         8 my %options;
475              
476 3         11 my $template = $self->{templates}{LICENSE};
477 3         17 return $self->render( $template, \%options );
478             }
479              
480             sub _license_blurb {
481 48     48   157 my $self = shift;
482 48         63 my $license_blurb;
483 48         168 my $license_record = $self->_license_record();
484              
485 48 50       480 if ( defined $license_record ) {
486 48 50       136 if ( $license_record->{license} eq 'perl' ) {
487 48         104 $license_blurb = <<'EOT';
488             This distribution is free software; you can redistribute it and/or modify it
489             under the terms of either:
490              
491             a) the GNU General Public License as published by the Free Software
492             Foundation; either version 1, or (at your option) any later version, or
493              
494             b) the Artistic License version 1.0 or a later version.
495             EOT
496             }
497             else {
498 0         0 $license_blurb = $license_record->{blurb};
499             }
500             }
501             else {
502 0         0 $license_blurb = <<"EOT";
503             This program is released under the following license: $self->{license}
504             EOT
505             }
506 48         97 chomp $license_blurb;
507 48         181 return $license_blurb;
508             }
509              
510             =head2 Makefile_PL_guts($main_module, $main_pm_file)
511              
512             This method is called by L and returns text used to populate
513             Makefile.PL when the builder is L;
514             I<$main_pm_file> is the filename of the distribution's main module,
515             I<$main_module>.
516              
517             =cut
518              
519             sub Makefile_PL_guts { ## no critic 'NamingConventions::Capitalization'
520 1     1 1 282 my ( $self, $main_module, $main_pm_file ) = @_;
521 1         2 my %options;
522 1         3 $options{main_module} = $main_module;
523 1         3 $options{main_pm_file} = $main_pm_file;
524              
525 1         3 my $template = $self->{templates}{'Makefile.PL'};
526 1         3 return $self->render( $template, \%options );
527             }
528              
529             =head2 MANIFEST_SKIP_guts
530              
531             Implements the creation of a C file.
532              
533             =cut
534              
535             sub MANIFEST_SKIP_guts { ## no critic 'NamingConventions::Capitalization'
536 3     3 1 6 my $self = shift;
537 3         6 my %options;
538              
539 3         12 my $template = $self->{templates}{'MANIFEST.SKIP'};
540 3         12 return $self->render( $template, \%options );
541             }
542              
543             =head2 MI_Makefile_PL_guts($main_module, $main_pm_file)
544              
545             This method is called by L and returns text used to populate
546             Makefile.PL when the builder is L;
547             I<$main_pm_file> is the filename of the distribution's main module,
548             I<$main_module>.
549              
550             =cut
551              
552             sub MI_Makefile_PL_guts { ## no critic 'NamingConventions::Capitalization'
553 1     1 1 927 my ( $self, $main_module, $main_pm_file ) = @_;
554 1         3 my %options;
555 1         3 $options{main_module} = $main_module;
556 1         6 $options{main_pm_file} = $main_pm_file;
557              
558 1         5 my $template = $self->{templates}{'MI_Makefile.PL'};
559 1         6 return $self->render( $template, \%options );
560             }
561              
562             =head2 module_guts($module, $rtname)
563              
564             Implements the creation of a C file.
565              
566             =cut
567              
568             sub module_guts {
569 6     6 1 2147 my ( $self, $module, $rtname ) = @_;
570 6         14 my %options;
571 6         20 $options{module} = $module;
572 6         162 $options{rtname} = $rtname;
573              
574 6         17 my $template = $self->{templates}{'Module.pm'};
575 6         363 return $self->render( $template, \%options );
576             }
577              
578             =head2 README_guts($build_instructions)
579              
580             Implements the creation of a C file.
581              
582             =cut
583              
584             sub README_guts { ## no critic 'NamingConventions::Capitalization'
585 3     3 1 78 my ( $self, $build_instructions ) = @_;
586 3         8 my %options;
587 3         11 $options{build_instructions} = $build_instructions;
588              
589 3         9 my $template = $self->{templates}{'README'};
590 3         11 return $self->render( $template, \%options );
591             }
592              
593             =head2 perlcriticrc_guts
594              
595             Implements the creation of a C file.
596            
597             =cut
598              
599             sub perlcriticrc_guts {
600 3     3 1 8 my $self = shift;
601 3         5 my %options;
602              
603 3         10 my $template = $self->{templates}{perlcriticrc};
604 3         15 return $self->render( $template, \%options );
605             }
606              
607             =head2 server_pl_guts
608              
609             Implements the creation of a C file.
610              
611             =cut
612              
613             sub server_pl_guts {
614 3     3 1 9 my $self = shift;
615 3         5 my %options;
616 3         10 $options{main_module} = $self->{main_module};
617              
618 3         11 my $template = $self->{templates}{'server.pl'};
619 3         14 return $self->render( $template, \%options );
620             }
621              
622             =head2 t_guts(@modules)
623              
624             Implements the creation of test files. I<@modules> is a list of all the modules
625             in the distribution.
626              
627             =cut
628              
629             sub t_guts {
630 3     3 1 10 my ( $self, @opts ) = @_;
631 3         6 my %options;
632 3         13 $options{modules} = [@opts];
633 3         14 $options{modulenames} = [];
634 3         8 foreach ( @{ $options{modules} } ) {
  3         12  
635 6         481 push @{ $options{module_pm_files} }, $self->_module_to_pm_file($_);
  6         64  
636             }
637              
638 3         60 my %t_files;
639              
640 3         7 foreach ( grep { /[.]t\z/msx } keys %{ $self->{templates} } ) {
  57         424  
  3         103  
641 12         2884 my $template = $self->{templates}{$_};
642 12         43 $t_files{$_} = $self->render( $template, \%options );
643             }
644              
645 3         1413 return %t_files;
646             }
647              
648             =head2 tmpl_guts
649              
650             Implements the creation of template files.
651              
652             =cut
653              
654             sub tmpl_guts {
655 3     3 1 8 my ($self) = @_;
656 3         8 my %options; # unused in this function.
657              
658 3         23 my @dirparts = ( $self->{basedir}, 'share', 'templates' );
659 3         746 my $tdir = File::Spec->catdir(@dirparts);
660 3 50       97 if ( not -d $tdir ) {
661 3         1734 mkpath($tdir);
662 3         26 $self->progress("Created $tdir");
663             }
664              
665 3         29 my @t_files;
666 3         7 foreach
667 57         134 my $filename ( grep { /[.]html \z/msx } keys %{ $self->{templates} } )
  3         27  
668             {
669 3         10 my $template = $self->{templates}{$filename};
670 3         42 my $fname = File::Spec->catfile( @dirparts, $filename );
671 3         17 $self->create_file( $fname, $template );
672 3         748 $self->progress("Created $fname");
673 3         33 push @t_files, "share/templates/$filename";
674             }
675              
676 3         22 return @t_files;
677             }
678              
679             =head2 xt_guts(@modules)
680              
681             Implements the creation of test files for author tests. I<@modules> is a list
682             of all the modules in the distribution.
683              
684             =cut
685              
686             sub xt_guts {
687 3     3 1 13 my ( $self, @opts ) = @_;
688 3         8 my %options;
689 3         226 $options{modules} = [@opts];
690 3         11 $options{modulenames} = [];
691 3         10 foreach ( @{ $options{modules} } ) {
  3         15  
692 6         556 push @{ $options{module_pm_files} }, $self->_module_to_pm_file($_);
  6         38  
693             }
694              
695 3         62 my %xt_files;
696              
697 3         10 foreach ( grep { /[.]xt\z/msx } keys %{ $self->{templates} } ) {
  57         187  
  3         114  
698 9         3764 my $template = $self->{templates}{$_};
699 9         61 $_ =~ s/[.]xt\z/.t/msx; # change *.xt back to *.t
700 9         39 $xt_files{$_} = $self->render( $template, \%options );
701             }
702              
703 3         1039 return %xt_files;
704             }
705              
706             =head1 BUGS
707              
708             Please report any bugs or feature requests to
709             C, or through the web
710             interface at L. I will be notified, and then you'll
711             automatically be notified of progress on your bug as I make changes.
712              
713             =head1 AUTHOR
714              
715             Jaldhar H. Vyas, Ejaldhar at braincells.comE
716              
717             =head1 COPYRIGHT
718              
719             Copyright (C) 2012, Consolidated Braincells Inc. All Rights Reserved.
720              
721             This distribution is free software; you can redistribute it and/or modify it
722             under the terms of either:
723              
724             a) the GNU General Public License as published by the Free Software
725             Foundation; either version 1, or (at your option) any later version, or
726              
727             b) the Artistic License version 1.0 or a later version.
728              
729             The full text of the license can be found in the LICENSE file included
730             with this distribution.
731              
732             =head1 SEE ALSO
733              
734             L, L, L,
735             L, L.
736             L, L, L
737              
738             =cut
739              
740             1;