package Transform::Alert::TemplateGrp;
our $VERSION = '1.00'; # VERSION
# ABSTRACT: Base class for Transform::Alert template groups
use sanity;
use Moo;
use MooX::Types::MooseLike::Base qw(Bool Str ArrayRef RegexpRef HashRef InstanceOf ConsumerOf Maybe);
use Template 2.24;
use Data::Dump 'pp';
use File::Slurp 'read_file';
use String::Escape qw(elide printable);
use Module::Load; # yes, using both Class::Load and Module::Load, as M:L will load files
use Module::Metadata;
use namespace::clean;
has in_group => (
is => 'rwp',
isa => InstanceOf['Transform::Alert::InputGrp'],
weak_ref => 1,
handles => [ 'log' ],
);
has regexp => (
is => 'ro',
isa => Maybe[RegexpRef],
required => 1,
);
has munger => (
is => 'ro',
isa => ArrayRef[Str],
predicate => 1,
);
has outputs => (
is => 'ro',
isa => HashRef[ConsumerOf['Transform::Alert::Output']],
required => 1,
);
around BUILDARGS => sub {
my ($orig, $self) = (shift, shift);
my $hash = shift;
$hash = { $hash, @_ } unless ref $hash;
# temp hash with output objects
my $outs = delete $hash->{output_objs};
# replace OutputNames with Outputs
my $outputs = delete $hash->{outputname};
$outputs = [ $outputs ] unless (ref $outputs eq 'ARRAY');
$hash->{outputs} = { map {
$_ => ($outs->{$_} || die "OutputName '$_' doesn't have a matching Output block!")
} @$outputs };
# read template file
if ($hash->{templatefile}) { $hash->{regexp} = read_file( delete $hash->{templatefile} ); }
elsif ($hash->{template}) { $hash->{regexp} = delete $hash->{template}; }
else { $hash->{regexp} = undef; }
# work with inline templates (and file above)
if ($hash->{regexp} && not ref $hash->{regexp}) {
my $tmpl_text = $hash->{regexp};
$tmpl_text =~ s/^\s+|\s+$//g; # remove leading/trailing spaces
$tmpl_text =~ s/\r//g; # make sure it works for all line-endings
$tmpl_text = '^'.$tmpl_text.'$';
$hash->{regexp} = qr/$tmpl_text/;
}
# munger class
if (my $munger = delete $hash->{munger}) {
# variable parsing
my ($file, $class, $fc, $method);
($fc, $method) = split /-\>/, $munger, 2;
($file, $class) = split /\s+/, $fc, 2;
unless ($class) {
my $info = Module::Metadata->new_from_file($file);
$class = ($info->packages_inside)[0];
die "No packages found in $file!" unless $class;
}
$method ||= 'munge';
load $file;
$hash->{munger} = [ $class, $method ];
}
$orig->($self, $hash);
};
sub send_all {
my ($self, $vars) = @_;
my $log = $self->log;
$log->debug('Processing outputs...');
$log->trace('Variables (pre-munged):');
$log->trace( join "\n", map { ' '.$_ } split(/\n/, pp $vars) );
# Munge the data if configured
if ($self->munger) {
my ($class, $method) = @{ $self->munger };
no strict 'refs';
$vars = $class->$method($vars, $self);
unless ($vars) {
$log->debug('Munger cancelled output');
return 1;
}
$log->trace('Variables (post-munge):');
$log->trace( join "\n", map { ' '.$_ } split(/\n/, pp $vars) );
}
# Support multiple outputs, if the munger sent them
$vars = [ $vars ] unless (ref $vars eq 'ARRAY');
my $tt = Template->new();
foreach my $v (@$vars) {
foreach my $out_key (keys %{ $self->outputs }) {
$log->debug('Looking at Output "'.$out_key.'"...');
my $out = $self->outputs->{$out_key};
my $out_str = '';
$tt->process($out->template, $v, \$out_str) || do {
$log->error('TT error for "$out_key": '.$tt->error);
$log->warn('Output error... bailing out of this process cycle!');
$self->close_all;
return;
};
# send alert
unless ($out->opened) {
$log->debug('Opening output connection');
$out->open;
}
$log->info('Sending alert for "'.$out_key.'"');
$log->info(' Output message: '.printable(elide($out_str, int(2.5 ** $log->level) )) );
unless ($out->send(\$out_str)) {
$log->warn('Output error... bailing out of this process cycle!');
$self->close_all;
return;
}
}
}
return 1;
}
sub close_all {
my $self = shift;
$_->close for (values %{ $self->outputs });
return 1;
}
42;
__END__
=pod
=encoding utf-8
=head1 NAME
Transform::Alert::TemplateGrp - Base class for Transform::Alert template groups
=head1 SYNOPSIS
# In your configuration
<Input ...>
<Template> # one or more
# Template/File can be optional
TemplateFile [file] # not used with Template
Template "[String]" # not used with TemplateFile
Munger [file] [class]->[method] # optional
OutputName test_out # one or more
</Template>
</Input>
=head1 DESCRIPTION
This is essentially a class used for handling C<<< Template >>> sections. In the grand scheme of things, the classes follow this hierarchy:
transalert_ctl
Transform::Alert
TA::InputGrp
TA::Input::*
TA::TemplateGrp
TA::Output::* (referenced from the main TA object)
TA::Output::* (stored list only)
In fact, the configuration file is parsed recursively in this fashion.
However, this isn't really a user-friendly interface. So, shoo!
=head1 SEE ALSO
L<Transform::Alert>, which is what you should really be reading...
=head1 AVAILABILITY
The project homepage is L<https://github.com/SineSwiper/Transform-Alert/wiki>.
The latest version of this module is available from the Comprehensive Perl
Archive Network (CPAN). Visit L<http://www.perl.com/CPAN/> to find a CPAN
site near you, or see L<https://metacpan.org/module/Transform::Alert/>.
=head1 AUTHOR
Brendan Byrd <BBYRD@CPAN.org>
=head1 COPYRIGHT AND LICENSE
This software is Copyright (c) 2013 by Brendan Byrd.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)
=cut