File Coverage

blib/lib/Data/Tubes/Plugin/Writer.pm
Criterion Covered Total %
statement 79 90 87.7
branch 18 22 81.8
condition 5 11 45.4
subroutine 18 28 64.2
pod 2 2 100.0
total 122 153 79.7


line stmt bran cond sub pod time code
1             package Data::Tubes::Plugin::Writer;
2              
3             # vim: ts=3 sts=3 sw=3 et ai :
4              
5 2     2   1519 use strict;
  2         4  
  2         58  
6 2     2   10 use warnings;
  2         4  
  2         53  
7 2     2   10 use English qw< -no_match_vars >;
  2         4  
  2         9  
8 2     2   755 use POSIX qw< strftime >;
  2         4  
  2         21  
9             our $VERSION = '0.738';
10              
11 2     2   3173 use Log::Log4perl::Tiny qw< :easy :dead_if_first LOGLEVEL >;
  2         3  
  2         16  
12 2     2   1328 use Template::Perlish;
  2         4079  
  2         25  
13              
14             use Data::Tubes::Util
15 2     2   76 qw< normalize_args read_file_maybe shorter_sub_names sprintffy >;
  2         3  
  2         146  
16 2     2   580 use Data::Tubes::Plugin::Util qw< identify log_helper >;
  2         5  
  2         106  
17 2     2   584 use Data::Tubes::Plugin::Plumbing;
  2         36  
  2         2218  
18             my %global_defaults = (input => 'rendered',);
19              
20             sub _filenames_generator {
21 14     14   28 my $template = shift;
22              
23 14         27 my $n = 0; # counter, used in closures inside $substitutions
24             my $substitutions = [
25 31     31   202 [qr{(\d*)n} => sub { return sprintf "%${1}d", $n; }],
26 0     0   0 [qr{Y} => sub { return strftime('%Y', localtime()); }],
27 0     0   0 [qr{m} => sub { return strftime('%m', localtime()); }],
28 0     0   0 [qr{d} => sub { return strftime('%d', localtime()); }],
29 0     0   0 [qr{H} => sub { return strftime('%H', localtime()); }],
30 0     0   0 [qr{M} => sub { return strftime('%M', localtime()); }],
31 0     0   0 [qr{S} => sub { return strftime('%S', localtime()); }],
32 0     0   0 [qr{z} => sub { return strftime('%z', localtime()); }],
33 0     0   0 [qr{D} => sub { return strftime('%Y%m%d', localtime()); }],
34 0     0   0 [qr{T} => sub { return strftime('%H%M%S%z', localtime()); }],
35 14     0   319 [qr{t} => sub { return strftime('%Y%m%dT%H%M%S%z', localtime()); }],
  0         0  
36             ];
37              
38             # see if the template depends on the counter
39 14         62 my $expanded = sprintffy($template, $substitutions);
40             return sub {
41 20     20   52 my $retval = sprintffy($template, $substitutions);
42 20         36 ++$n;
43 20         55 return $retval;
44             }
45 14 100       73 if ($expanded ne $template); # it does!
46              
47             # then, by default, revert to poor's man expansion of name...
48             return sub {
49 5 100   5   16 my $retval = $n ? "${template}_$n" : $template;
50 5         8 ++$n;
51 5         13 return $retval;
52 3         45 };
53             } ## end sub _filenames_generator
54              
55             sub dispatch_to_files {
56 5     5 1 30656 my %args = normalize_args(
57             @_,
58             [
59             {
60             %global_defaults,
61             name => 'write dispatcher',
62             binmode => ':encoding(UTF-8)'
63             },
64             'filename'
65             ],
66             );
67 5         39 identify(\%args);
68 5         15 my $name = delete $args{name}; # so that it can be overridden
69              
70 5 100       27 if (defined(my $filename = delete $args{filename})) {
71 3         5 my $ref = ref $filename;
72 3 100       15 if (!$ref) {
    50          
73 2   33     11 $args{filename_template} //= $filename;
74             }
75             elsif ($ref eq 'CODE') {
76 1   33     8 $args{filename_factory} //= $filename;
77             }
78             else {
79 0         0 LOGDIE "argument filename has invalid type $ref";
80             }
81             } ## end if (defined(my $filename...))
82              
83 5         11 my $factory = delete $args{filename_factory};
84 5 100 66     19 if (!defined($factory) && defined($args{filename_template})) {
85 3 50       5 my $tp = Template::Perlish->new(%{$args{tp_opts} || {}});
  3         28  
86 3         83 my $template = $tp->compile($args{filename_template});
87             $factory = sub {
88 6     6   56 my ($key, $record) = @_;
89 6         69 return $tp->evaluate($template, {key => $key, record => $record});
90 3         3025 };
91             } ## end if (!defined($factory)...)
92              
93             $args{factory} //= sub {
94 10     10   42 my $filename = $factory->(@_);
95 10         2375 return write_to_files(%args, filename => $filename);
96 5   50     47 };
97              
98 5         50 return Data::Tubes::Plugin::Plumbing::dispatch(%args);
99             } ## end sub dispatch_to_files
100              
101             sub write_to_files {
102 16     16 1 12961 my %args = normalize_args(
103             @_,
104             [
105             {
106             %global_defaults,
107             name => 'write to file',
108             binmode => ':encoding(UTF-8)',
109             filename => \*STDOUT,
110             },
111             'filename'
112             ],
113             );
114 16         87 identify(\%args);
115 16         44 my $name = $args{name};
116 16 50       38 LOGDIE "$name: need a filename" unless defined $args{filename};
117 16 50       34 LOGDIE "$name: need an input" unless defined $args{input};
118              
119 16         25 my $output = $args{filename};
120 16 100       50 $output = _filenames_generator($output) unless ref($output);
121              
122             my %oha =
123 28         88 map { ($_ => $args{$_}) }
124 16         36 grep { defined $args{$_} } qw< binmode policy >;
  32         91  
125 16         35 for my $marker (qw< footer header interlude >) {
126             $oha{$marker} = read_file_maybe($args{$marker})
127 48 100       366 if defined $args{$marker};
128             }
129 16         693 require Data::Tubes::Util::Output;
130 16         127 my $output_handler =
131             Data::Tubes::Util::Output->new(%oha, output => $output,);
132              
133 16         257 my $input = $args{input};
134             return sub {
135 33     33   112 my $record = shift;
136 33         119 $output_handler->print($record->{$input});
137 33         126 return $record; # relaunch for further processing
138 16         136 };
139             } ## end sub write_to_files
140              
141             shorter_sub_names(__PACKAGE__, 'write_');
142              
143             1;