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   7100 use strict;
  2         5  
  2         64  
6 2     2   11 use warnings;
  2         3  
  2         60  
7 2     2   9 use English qw< -no_match_vars >;
  2         4  
  2         14  
8 2     2   803 use POSIX qw< strftime >;
  2         7  
  2         17  
9             our $VERSION = '0.740';
10              
11 2     2   3324 use Log::Log4perl::Tiny qw< :easy :dead_if_first LOGLEVEL >;
  2         6  
  2         17  
12 2     2   1270 use Template::Perlish;
  2         3924  
  2         30  
13              
14             use Data::Tubes::Util
15 2     2   84 qw< normalize_args read_file_maybe shorter_sub_names sprintffy >;
  2         4  
  2         143  
16 2     2   545 use Data::Tubes::Plugin::Util qw< identify log_helper >;
  2         6  
  2         101  
17 2     2   594 use Data::Tubes::Plugin::Plumbing;
  2         37  
  2         2501  
18             my %global_defaults = (input => 'rendered',);
19              
20             sub _filenames_generator {
21 14     14   24 my $template = shift;
22              
23 14         20 my $n = 0; # counter, used in closures inside $substitutions
24             my $substitutions = [
25 31     31   175 [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   323 [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         57 my $expanded = sprintffy($template, $substitutions);
40             return sub {
41 20     20   44 my $retval = sprintffy($template, $substitutions);
42 20         38 ++$n;
43 20         47 return $retval;
44             }
45 14 100       66 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   17 my $retval = $n ? "${template}_$n" : $template;
50 5         9 ++$n;
51 5         15 return $retval;
52 3         46 };
53             } ## end sub _filenames_generator
54              
55             sub dispatch_to_files {
56 5     5 1 30529 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         14 my $name = delete $args{name}; # so that it can be overridden
69              
70 5 100       16 if (defined(my $filename = delete $args{filename})) {
71 3         7 my $ref = ref $filename;
72 3 100       13 if (!$ref) {
    50          
73 2   33     12 $args{filename_template} //= $filename;
74             }
75             elsif ($ref eq 'CODE') {
76 1   33     7 $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         8 my $factory = delete $args{filename_factory};
84 5 100 66     20 if (!defined($factory) && defined($args{filename_template})) {
85 3 50       8 my $tp = Template::Perlish->new(%{$args{tp_opts} || {}});
  3         24  
86 3         72 my $template = $tp->compile($args{filename_template});
87             $factory = sub {
88 6     6   57 my ($key, $record) = @_;
89 6         56 return $tp->evaluate($template, {key => $key, record => $record});
90 3         2538 };
91             } ## end if (!defined($factory)...)
92              
93             $args{factory} //= sub {
94 10     10   31 my $filename = $factory->(@_);
95 10         2008 return write_to_files(%args, filename => $filename);
96 5   50     36 };
97              
98 5         28 return Data::Tubes::Plugin::Plumbing::dispatch(%args);
99             } ## end sub dispatch_to_files
100              
101             sub write_to_files {
102 16     16 1 15018 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         81 identify(\%args);
115 16         34 my $name = $args{name};
116 16 50       34 LOGDIE "$name: need a filename" unless defined $args{filename};
117 16 50       35 LOGDIE "$name: need an input" unless defined $args{input};
118              
119 16         22 my $output = $args{filename};
120 16 100       43 $output = _filenames_generator($output) unless ref($output);
121              
122             my %oha =
123 28         87 map { ($_ => $args{$_}) }
124 16         33 grep { defined $args{$_} } qw< binmode policy >;
  32         83  
125 16         48 for my $marker (qw< footer header interlude >) {
126             $oha{$marker} = read_file_maybe($args{$marker})
127 48 100       280 if defined $args{$marker};
128             }
129 16         673 require Data::Tubes::Util::Output;
130 16         119 my $output_handler =
131             Data::Tubes::Util::Output->new(%oha, output => $output,);
132              
133 16         229 my $input = $args{input};
134             return sub {
135 33     33   99 my $record = shift;
136 33         107 $output_handler->print($record->{$input});
137 33         121 return $record; # relaunch for further processing
138 16         118 };
139             } ## end sub write_to_files
140              
141             shorter_sub_names(__PACKAGE__, 'write_');
142              
143             1;