File Coverage

blib/lib/Database/Format/Text.pm
Criterion Covered Total %
statement 18 195 9.2
branch 0 82 0.0
condition 0 20 0.0
subroutine 6 16 37.5
pod 7 7 100.0
total 31 320 9.6


line stmt bran cond sub pod time code
1             package Database::Format::Text;
2              
3             # Use tab width 8 to view at its best :).
4              
5 1     1   29667 use 5.006;
  1         7  
  1         59  
6 1     1   5 use strict;
  1         2  
  1         36  
7 1     1   5 use warnings FATAL => 'all';
  1         13  
  1         43  
8 1     1   5 use Carp;
  1         1  
  1         64  
9 1     1   6 use File::Spec;
  1         1  
  1         17  
10 1     1   748 use File::Copy;
  1         4966  
  1         3766  
11              
12             =head1 NAME
13              
14             Database::Format::Text - Local database in text format.
15              
16             =head1 VERSION
17              
18             Version 1.03
19              
20             =cut
21              
22             our $VERSION = '1.03';
23              
24              
25             =head1 SYNOPSIS
26              
27             C module is handy tool to create a text based database
28             on local machine. This module will create database in text format, so user
29             can any time open the text file and look at the data. User will be able to do
30             following manipulation on the data base using this module.
31              
32             =over 4
33              
34             =item * Add data
35              
36             =item * Delete data
37              
38             =item * Append data
39              
40             =item * Get titles
41              
42             =item * Get data
43              
44             =item * Get whole data base
45              
46             =item * Count entries
47              
48             =back
49              
50             To modify the existing entry, delete the existing entry and re-enter the modified
51             entry. Following is the example to use C
52              
53             use Database::Format::Text;
54             my @titles = qw(Number Title Status Comments);
55              
56             # Create database
57             my $foo_data_table = Database::Format::Text->new('file_name' => "foo_data",
58             'fields' => \@titles);
59             # Add entry
60             my $status = $foo_data_table->add_entry("1", "Test1", "Pass", "Applicable");
61              
62             # Delete entry
63             $status = $foo_data_table->delete_entry("Status", "Pass");
64              
65             # Get entry
66             my @data = foo_data_table->get_entry("Number", 7);
67             # or
68             $status = foo_data_table->get_entry("Number", 7, "Status");
69              
70             # Get database
71             my @database = $foo_data_table->get_table();
72              
73             # Count entries
74             $status = $foo_data_table->count_entry("Status", "Pass");
75              
76             # Get titles
77             @database = $foo_data_table->get_titles();
78              
79             You can use this module at many places. Example : If you are a test engineer and
80             you need to perform some test cases on your product this data base will help to
81             store your records. It is in text based format so you can copy this data base
82             in your archive for future reference.
83              
84             =head1 SUBROUTINES
85              
86             =head2 new
87              
88             Creates and returns a new Database::Format::Text object.
89              
90             my @titles = qw(Number Title Status Comments [ . . .]);
91             # User can add N number of columns here.
92             my $foo_data_table = Database::Format::Text->new('file_name' => "foo_data",
93             'fields' => \@titles);
94              
95             Constructor needs 2 parameters. Without above 2 parameters program will die. 2
96             parameters are file name and titles for database. File name is required to store
97             the database. Fields are titles of the column of your database.
98             In above example user will create a database in text format in file "foo_data".
99             Which will have 4 columns. Columns would be Number, Title, Status and Comments.
100              
101             Here are the parameters that Database::Format::Text recognizes. These are optional.
102              
103             =over 4
104              
105             =item * C<< 'location' => '/your/folder/to/store/database' >>
106              
107             This variable will store the folder location. Database::Format::Text module will
108             create a database in text format in above mentioned location or if above
109             parameter is not defined then it will store database in current working directory.
110              
111             =item * C<< 'delimiter' => '|' >>
112              
113             Database will have many fields. Each field is divided by delimiter. Use this
114             variable to specify the delimiter of your database. If this is not supplied,
115             Database::Format::Text will use ':' as the delimiter.
116              
117              
118             =item * C<< 'append' => [0|1] >>
119              
120             If you want to create a single database and run your perl program multiple times
121             on the same database then use this variable. If it is enabled the database will
122             append the new records. If this is disabled Database::Format::Text will
123             delete old database and and create a new database.
124              
125             =item * C<< 'column_width' => 20 >>
126              
127             Based on your data select this variable. Above example will create 20 width column
128             for each of the entry.
129              
130             =item * C<< 'die' => [0|1] >>
131              
132             During many sanity tests Database::Format::Text will die your program if
133             any failure. If you want to continue without dyeing, enable this variable.
134              
135             =back
136              
137             =cut
138              
139             sub new {
140 0     0 1   my $class = shift;
141 0           my %user_args = @_;
142              
143             #
144             # process user arguments.
145             #
146 0 0 0       if (! defined $user_args{'file_name'} || ! defined $user_args{'fields'}[0]) {
147 0           die "Define file_name and fields variables";
148             # Just die if mandatory variables are not provided.
149             }
150 0           _test_unique_fields(@{$user_args{'fields'}});
  0            
151             # Make sure all the titles are unique.
152 0 0         my $location = ((defined $user_args{'location'}) ? ($user_args{'location'}) : ('.'));
153             # This is the location to create user data table.
154 0 0         my $delimiter = ((defined $user_args{'delimiter'}) ? ($user_args{'delimiter'}) : (':'));
155             # This will separate each records in data table.
156 0 0         my $append = ((defined $user_args{'append'}) ? ($user_args{'append'}) : (0));
157             # If enable do not delete all data table.
158 0 0         my $column_width = ((defined $user_args{'column_width'}) ? ($user_args{'column_width'}) : (10));
159             # This will produce uniform output in the data table.
160 0           my $l_o_f = $location . "/" . $user_args{'file_name'};
161             # The complete location to file.
162 0           $l_o_f = File::Spec->canonpath($l_o_f);
163             # User can use this on Linux as well as on Windows.
164 0 0         my $die = ((defined $user_args{'die'}) ? ($user_args{'die'}) : 1);
165             # Script will die out if enable
166 0           my $f_c = @{$user_args{'fields'}};
  0            
167             # Variable to provide sanity.
168              
169             #
170             # The hash reference is created.
171             #
172 0           my $data_table_ref = {
173             'file_name' => $user_args{'file_name'},
174 0           'fields' => \@{$user_args{'fields'}},
175             'location' => $location,
176             'delimiter' => $delimiter,
177             'append' => $append,
178             'column_width' => $column_width,
179             'die' => $die,
180             'l_o_f' => $l_o_f,
181             'f_c' => $f_c,
182             };
183              
184             #
185             # Create data file. Do not create a new file if append is enabled.
186             #
187 0 0 0       unless (defined $data_table_ref->{'append'} && $data_table_ref->{'append'} == 1 && -f $data_table_ref->{'l_o_f'}) {
      0        
188 0           my ($pattern, @entry);
189              
190             #
191             # Open the new file in write mode.
192             #
193 0 0         open(DT, ">" , $data_table_ref->{'l_o_f'}) or _die($data_table_ref, "Failed to create a data table file $!");
194 0           @entry = @{$data_table_ref->{'fields'}};
  0            
195            
196             #
197             # Create and print the pattern.
198             #
199 0           foreach (0 .. $#entry) {
200 0 0         if ($_ == $#entry) {
201 0           $pattern = $pattern . sprintf ( "%-$data_table_ref->{column_width}s \n", $entry[$_]);
202             } else {
203 0           $pattern = $pattern . sprintf ( "%-$data_table_ref->{column_width}s $data_table_ref->{delimiter} ", $entry[$_]);
204             }
205             }
206 0           print DT $pattern;
207              
208             #
209             # Close the opened file.
210             #
211 0           close(DT);
212             }
213              
214             #
215             # blessing the class.
216             #
217 0           bless($data_table_ref);
218 0           return $data_table_ref;
219             }
220              
221             =head2 $foo_data_table->add_entry(@data_records)
222              
223             This method will create an actual data entry into your database. This method takes
224             list of data. In our example we have 4 columns; Number, Title, Status and Comments.
225             Therefore our data to be entered is 4. For example it is 1, Test1, Pass and
226             Applicable.
227              
228             my @data_records = ("1", "Test1", "Pass", "Applicable");
229             $foo_data_table->add_entry(@data_records);
230              
231             This database will have an entry with above data. If this method
232             creates the entry, it will return 0.
233              
234             =cut
235              
236             sub add_entry {
237 0     0 1   my $this = shift;
238 0           my @entry = @_;
239 0           my $pattern;
240              
241             #
242             # Sanity test on users provided data.
243             #
244 0 0 0       (warn ("Failed to add mismatch in number of titles and records!\nNumber of record has to be $this->{f_c}\nNumber of elements are not equal to $this->{f_c}.\nThe elements are @entry\n") && (return -1)) if (@entry != $this->{'f_c'});
245              
246             #
247             # Open the data base table and add the entry.
248             #
249 0 0         open(DT, ">>" , $this->{l_o_f}) or _die($this, "Failed to create a data table file $!");
250              
251             #
252             # Create the pattern.
253             #
254 0           foreach (0 .. $#entry) {
255 0 0         if ($_ == $#entry) {
256 0           $pattern = $pattern . sprintf ( "%-$this->{column_width}s \n", $entry[$_]);
257             } else {
258 0           $pattern = $pattern . sprintf ( "%-$this->{column_width}s $this->{delimiter} ", $entry[$_]);
259             }
260             }
261              
262             #
263             # Print the pattern.
264             #
265 0           print DT $pattern;
266              
267             #
268             # Close the opened file.
269             #
270 0           close(DT);
271 0           return 0;
272             }
273              
274             =head2 $foo_data_table->delete_entry($title, $record)
275              
276             After creating database, if you need to remove one entry from your database, use
277             this method to remove entry. It takes 2 arguments. One is title. You can remove
278             entry using any title. In our example I will remove entry using title "Status".
279             2nd argument is actual record itself. In our example I would like remove entries
280             with record as Pass. I will use below code as my example.
281              
282             my $status = $foo_data_table->delete_entry("Status", "Pass");
283              
284             This code will search pattern "Pass" under "Status" in your database and remove
285             all matched entries. This method will return number of removed entries. If it did
286             not find above pattern in your database, it will return 0. If it finds multiple
287             entries, this method will erase all matched entries. In above example if this method
288             finds 5 data as "Passing" under column "Status", method will delete all 5 entries
289             and return 5.
290              
291             =cut
292              
293             sub delete_entry {
294 0     0 1   my $this = shift;
295 0           my $field_name = shift; # Title.
296 0           my $record = shift; # Record needs manipulation.
297 0           my @all_fields; # Holds all the titles.
298             my @database_line; # Holds data table lines.
299 0           my $given_field_index; # Index of the titles to the @all_fields.
300 0           my $count = 0; # Counts the number of entries deleted.
301              
302             #
303             # Open database file to read titles.
304             #
305 0 0         open(DT, "<" , $this->{'l_o_f'}) or _die($this, "Failed to open up data table file $!");
306 0           while(
) {
307 0           @all_fields = split(/$this->{'delimiter'}/, $_);
308 0           last;
309             }
310              
311             #
312             # Close the opened database table file.
313             #
314 0           close(DT);
315              
316             #
317             # Remove head and trail white spaces.
318             #
319 0           map {s#^\s*(\w*.*\w)\s*$#$1#} @all_fields;
  0            
320 0           map {s#^\s+$# #} @all_fields;
  0            
321              
322             #
323             # Give sanity on users data.
324             #
325 0 0         _die($this, "The field \"${field_name}\" does not exist in list \"@{all_fields}\"") unless (grep(/^$field_name$/,@all_fields));
326              
327             #
328             # Copy the original data table to tmp file.
329             #
330 0 0         copy($this->{'l_o_f'}, ".tmp") or _die($this, "Copy failed: $!");
331              
332             #
333             # Check for the tmp existence.
334             #
335 0 0         unless (-f ".tmp") {
336 0           warn "Fatal Error: Failed to create a back up file, unable to delete entry";
337 0           return;
338             }
339              
340             #
341             # Re-open the data table file with write mode.
342             #
343 0 0         open(DT, ">" , $this->{'l_o_f'}) or _die($this, "Failed to open up data table file $!");
344            
345             #
346             # Search for index of field_name.
347             #
348 0           foreach (0 .. $#all_fields) {
349 0 0         ($given_field_index = $_) if ( $all_fields[$_] eq $field_name );
350             }
351              
352             #
353             # Open new temporary file.
354             #
355 0 0         open(TMP, "<", ".tmp") or _die($this, "Failed to open up data table file ('') $!");
356 0           while() {
357 0 0         if ($_ =~ m/$record/) {
358 0           @database_line = split(/$this->{'delimiter'}/, $_);
359 0           map { s/^\s*(\w*.*\w)\s*$/$1/ } @database_line;
  0            
360             # Remove trailing and heading white spaces.
361 0           map { s/^\s+$/ / } @database_line;
  0            
362             # Remove multiple spaces.
363 0 0         if ($database_line[$given_field_index] eq $record) {
364 0           ++$count;
365 0           next;
366             }
367             }
368 0           print DT $_;
369             }
370              
371             #
372             # Close both the files.
373             #
374 0           close(TMP);
375 0           close(DT);
376              
377             #
378             # Delete the temporary file.
379             #
380 0           unlink(".tmp");
381 0           return $count; # $return will hold count for deletion happened.
382             }
383              
384             =head2 $foo_data_table->count_entry($title, $record)
385              
386             After creating database, if you need to count number of entries for specific record,
387             use this method. In above example if you want to count how many test
388             are passed use this method. It takes 2 arguments. One is title. You can find
389             entry using any title. In our example I will count entry using title "Status".
390             2ns argument is actual record. In our example I would like count entries with
391             record as Pass. I will use below code as my example.
392              
393             my $status = $foo_data_table->count_entry("Status", "Pass");
394              
395             This code will search pattern "Pass" under "Status" in your database and count
396             all matched entries. This method will return number of matched entries. If it did
397             not find above pattern in your database, it will return 0.
398              
399             =cut
400              
401             sub count_entry {
402 0     0 1   my $this = shift;
403 0           my $count = 0;
404 0           my $field_name = shift; # Title.
405 0           my $record = shift; # Record needs manipulation.
406 0           my @all_fields; # Holds all the titles.
407             my @database_line; # Holds data table lines.
408 0           my $given_field_index; # Index of the titles to the @all_fields.
409              
410             #
411             # Open database file
412             #
413 0 0         open(DT, "<" , $this->{'l_o_f'}) or _die($this, "Failed to open up data table file $!");
414            
415 0           while(
) {
416 0           @all_fields = split(/$this->{'delimiter'}/, $_);
417 0           last;
418             }
419              
420             #
421             # Remove head and trail white spaces
422             #
423 0           map { s/^\s*(\w*.*\w)\s*$/$1/ } @all_fields;
  0            
424 0           map { s/^\s+$/ / } @all_fields;
  0            
425              
426             #
427             # Give sanity on users data
428             #
429 0 0         _die($this, "The field \"${field_name}\" does not exist in list \"@{all_fields}\"") unless (grep(/^$field_name$/,@all_fields));
430              
431             #
432             # Search for index of field_name
433             #
434 0           foreach (0 .. $#all_fields) {
435 0 0         ($given_field_index = $_) if ( $all_fields[$_] eq $field_name );
436             }
437              
438             #
439             # Search for the record
440             #
441 0           while (
) {
442 0 0         if ($_ =~ m/$record/) {
443 0           @database_line = split(/$this->{'delimiter'}/, $_);
444 0           map { s/^\s*(\w*.*\w)\s*$/$1/ } @database_line;
  0            
445             # Remove trailing and heading white spaces.
446 0           map { s/^\s+$/ / } @database_line;
  0            
447             # Remove multiple spaces.
448 0 0         if ($database_line[$given_field_index] eq $record) {
449 0           ++$count;
450             }
451             }
452             }
453 0           close(DT);
454 0           return $count;
455             }
456              
457             =head2 $foo_data_table->get_entry($title, $record, [$title_of_needed_data])
458              
459             After creating database, if you need to get a particular entry from the database
460             use this method. This method will take 3 arguments. 1st argument is title. For
461             example you want to get entry for column "Number". Use "Number as your 1st arguement.
462             2nd arguement will be record. For example you want to get entry for Column "Number"
463             with "7". Use "7" as your 2nd arguement. In our example this method will go to
464             database and get complete entry for the column "Number" == "7". This will return
465             as a list. List will contain all the record of column "Number" with 7. If it finds
466             multiple entries, this method will fetch all and return to you as a list.
467              
468             my @data = foo_data_table->get_entry("Number", 7);
469              
470              
471             If we need only specific data then also specify 3rd arguement, which is title to
472             be needed. For example If you want "Status" of "Number" == "7". Use title "Status
473             as your 3rd arguement. This will retun a scalar value. This will be 1st matched
474             pattern. If you have multiple entries pass only 2 arguments as above.
475              
476             my $status = foo_data_table->get_entry("Number", 7, "Status");
477              
478             This will return value stored under "Status" whose "Number" is 7.
479              
480             =cut
481              
482             sub get_entry {
483 0     0 1   my $this = shift;
484 0           my $field_name = shift; # Title.
485 0           my $record = shift; # Record needs manipulation.
486 0 0         my $specific_field = shift if @_; # Query title.
487 0           my @all_fields; # Holds all the titles.
488             my @database_line; # Holds data table lines.
489 0           my $given_field_index; # Index of the titles to the @all_fields.
490 0           my $searching_field_index; # Index of the titles to the @all_fields.
491 0           my @record_found; # Holds matched pattern.
492              
493             #
494             # Open database file.
495             #
496 0 0         open(DT, "<" , $this->{'l_o_f'}) or _die($this, "Failed to open up data table file $!");
497 0           while(
) {
498 0           @all_fields = split(/$this->{'delimiter'}/, $_);
499 0           last;
500             }
501              
502             #
503             # Remove head and trail white spaces.
504             #
505 0           map { s/^\s*(\w*.*\w)\s*$/$1/ } @all_fields;
  0            
506 0           map { s/^\s+$/ / } @all_fields;
  0            
507              
508             #
509             # Give sanity on users data.
510             #
511 0 0         _die($this, "The field \"${field_name}\" does not exist in list \"@{all_fields}\"") unless (grep(/^$field_name$/,@all_fields));
512 0 0 0       _die($this, "The field \"${specific_field}\" does not exist in list \"@{all_fields}\"") if (defined $specific_field && ! grep(/^$specific_field$/,@all_fields));
513 0 0 0       _die($this, "The given field name \"${field_name}\" can not be same as searching field name\"${specific_field}\"") if (defined $specific_field && ($specific_field eq $field_name));
514              
515             #
516             # Search for index of field_name.
517             #
518 0           foreach (0 .. $#all_fields) {
519 0 0         ($given_field_index = $_) if ( $all_fields[$_] eq $field_name );
520             }
521              
522             #
523             # Search for index of specific_field.
524             #
525 0 0         if(defined $specific_field) {
526 0           foreach (0 .. $#all_fields) {
527 0 0         $searching_field_index = $_ if ( $all_fields[$_] eq $specific_field );
528             }
529             }
530              
531             #
532             # Search for the record.
533             #
534 0           while (
) {
535 0 0         if ($_ =~ m/$record/) {
536 0           @database_line = split(/$this->{'delimiter'}/, $_);
537 0           map { s/^\s*(\w*.*\w)\s*$/$1/ } @database_line;
  0            
538             # Remove trailing and heading white spaces.
539 0           map { s/^\s+$/ / } @database_line;
  0            
540             # Remove multiple spaces.
541 0 0         push (@record_found, @database_line) if ($database_line[$given_field_index] eq $record);
542 0 0 0       return ($database_line[$searching_field_index]) if (defined $specific_field && $database_line[$given_field_index] eq $record);
543             }
544             }
545 0           close(DT);
546 0           return @record_found;
547             }
548              
549             =head2 $foo_data_table->get_table()
550              
551             This method does not take any arguments. This method will return complete database
552             in list.
553              
554             my @database = $foo_data_table->get_table();
555             =cut
556              
557             sub get_table {
558 0     0 1   my $this = shift;
559 0           my @database_lines; # This will hold all the records.
560              
561             #
562             # Open database file in read mode and read the entire file.
563             #
564 0 0         open(DT, "<" , $this->{'l_o_f'}) or _die($this, "Failed to open up data table file $!");
565 0           while(
) {
566 0           last;
567             }
568              
569             #
570             # Search for the record.
571             #
572 0           @database_lines =
;
573 0           close(DT);
574 0           return @database_lines;
575             }
576              
577             =head2 $foo_data_table->get_titles()
578              
579             This method does not take any arguments. This method will return all the titles
580             of the database.
581              
582             my @database = $foo_data_table->get_titles();
583             =cut
584              
585             sub get_titles {
586 0     0 1   my $this = shift;
587 0           my @all_fields; # Holds all the titles.
588              
589             #
590             # Open database file.
591             #
592 0 0         open(DT, "<" , $this->{'l_o_f'}) or _die($this, "Failed to open up data table file $!");
593 0           while(
) {
594 0           @all_fields = split(/$this->{'delimiter'}/, $_);
595 0           last;
596             }
597              
598             #
599             # Remove head and trail white spaces.
600             #
601 0           map { s/^\s*(\w*.*\w)\s*$/$1/ } @all_fields;
  0            
602 0           map { s/^\s+$/ / } @all_fields;
  0            
603              
604             #
605             # Close the opened file.
606 0           close(DT);
607 0           return @all_fields; # return all the titles.
608             }
609              
610             #
611             # Internal method:
612             # _test_unique_fields()
613             # All fields must be unique.
614             #
615             sub _test_unique_fields {
616 0     0     my @fields = @_;
617 0           my $count = 0;
618 0           my $pattern;
619              
620             #
621             # Die if the fields are not unique.
622             #
623 0           while ($pattern = pop @fields) {
624 0           foreach my $field (@fields) {
625 0 0         die "Field name has to be unique. \"${pattern}\" is not unique in list: \"@{_}\"" if ($field eq $pattern);
626             }
627             }
628             }
629              
630             #
631             # _die()
632             # die if it is enable.
633             #
634             sub _die {
635 0     0     my $this = shift;
636 0           my $msg = shift;
637            
638             #
639             # Die if it is enable through user else warn user and return negative value.
640             #
641 0 0         if($this->{'die'} == 1) {
642 0           die "Fatal error: $msg\n";
643             } else {
644 0           warn "Error: $msg\n";
645 0           return -1;
646             }
647             }
648              
649             #
650             # Internal method:
651             # DESTROY()
652             # Destructor of the class.
653             #
654             sub DESTROY {
655 0     0     my $this = shift;
656             }
657              
658             =head1 AUTHOR
659              
660             Devang Doshi, C<< >>
661              
662             =head1 BUGS
663              
664             Please report any bugs or feature requests to C, or through
665             the web interface at L. I will be notified, and then you'll
666             automatically be notified of progress on your bug as I make changes.
667              
668              
669              
670              
671             =head1 SUPPORT
672              
673             You can find documentation for this module with the perldoc command.
674              
675             perldoc Database::Format::Text
676              
677              
678             You can also look for information at:
679              
680             =over 4
681              
682             =item * RT: CPAN's request tracker (report bugs here)
683              
684             L
685              
686             =item * AnnoCPAN: Annotated CPAN documentation
687              
688             L
689              
690             =item * CPAN Ratings
691              
692             L
693              
694             =item * Search CPAN
695              
696             L
697              
698             =back
699              
700              
701             =head1 ACKNOWLEDGEMENTS
702              
703              
704             =head1 LICENSE AND COPYRIGHT
705              
706             Copyright 2013 Devang Doshi.
707              
708             This program is free software; you can redistribute it and/or modify it
709             under the terms of the Artistic License (2.0). You may obtain a
710             copy of the full license at:
711              
712             L
713              
714             Any use, modification, and distribution of the Standard or Modified
715             Versions is governed by this Artistic License. By using, modifying or
716             distributing the Package, you accept this license. Do not use, modify,
717             or distribute the Package, if you do not accept this license.
718              
719             If your Modified Version has been derived from a Modified Version made
720             by someone other than you, you are nevertheless required to ensure that
721             your Modified Version complies with the requirements of this license.
722              
723             This license does not grant you the right to use any trademark, service
724             mark, tradename, or logo of the Copyright Holder.
725              
726             This license includes the non-exclusive, worldwide, free-of-charge
727             patent license to make, have made, use, offer to sell, sell, import and
728             otherwise transfer the Package with respect to any patent claims
729             licensable by the Copyright Holder that are necessarily infringed by the
730             Package. If you institute patent litigation (including a cross-claim or
731             counterclaim) against any party alleging that the Package constitutes
732             direct or contributory patent infringement, then this Artistic License
733             to you shall terminate on the date that such litigation is filed.
734              
735             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
736             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
737             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
738             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
739             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
740             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
741             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
742             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
743              
744              
745             =cut
746              
747             1; # End of Database::Format::Text