File Coverage

blib/lib/Monitoring/Livestatus/Class/Base/Abstract.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package # Hide from pause
2             Monitoring::Livestatus::Class::Base::Abstract;
3              
4 1     1   5911 use Moose;
  0            
  0            
5             use Carp;
6             use List::Util qw/first/;
7              
8             use Monitoring::Livestatus::Class;
9             my $TRACE = Monitoring::Livestatus::Class->TRACE() || 0;
10              
11             has 'ctx' => (
12             is => 'rw',
13             handles => [qw/table_name backend_obj/],
14             );
15              
16             has 'mode' => (
17             is => 'ro',
18             isa => 'Str',
19             builder => 'build_mode',
20             );
21              
22             sub build_mode { die "build_mode must be implemented in " . ref(shift) };
23              
24             has 'operators' => (
25             is => 'ro',
26             isa => 'ArrayRef',
27             builder => 'build_operators',
28             );
29              
30             sub build_operators {
31             return [
32             {
33             regexp => qr/(and|or)/ix,
34             handler => '_cond_compining',
35             }
36             ]
37             };
38              
39             has 'compining_prefix' => (
40             is => 'ro',
41             isa => 'Str',
42             builder => 'build_compining_prefix',
43             );
44              
45             sub build_compining_prefix { return ''; };
46              
47              
48              
49             sub apply {
50             my $self = shift;
51             my $cond = shift;
52              
53             my ( $combining_count, @statments ) = $self->_recurse_cond($cond);
54              
55             return wantarray ? @statments : \@statments;
56             }
57              
58             sub _recurse_cond {
59             my $self = shift;
60             my $cond = shift;
61             my $combining_count = shift || 0;
62             print STDERR "#IN _recurse_cond $cond $combining_count\n" if $TRACE > 9;
63             my $method = $self->_METHOD_FOR_refkind("_cond",$cond);
64             my ( $child_combining_count, @statment ) = $self->$method($cond,$combining_count);
65             $combining_count = $child_combining_count;
66             print STDERR "#OUT _recurse_cond $cond $combining_count ( $method )\n" if $TRACE > 9;
67             return ( $combining_count, @statment );
68             }
69              
70             sub _cond_UNDEF { return ( () ); }
71              
72             sub _cond_ARRAYREF {
73             my $self = shift;
74             my $conds = shift;
75             my $combining_count = shift || 0;
76             print STDERR "#IN _cond_ARRAYREF $conds $combining_count\n" if $TRACE > 9;
77             my @statment = ();
78              
79             my $child_combining_count = 0;
80             my @child_statment = ();
81             my @cp_conds = @{ $conds }; # work with a copy
82             while ( my $cond = shift @cp_conds ){
83             my ( $child_combining_count, @child_statment ) = $self->_dispatch_refkind($cond, {
84             ARRAYREF => sub { $self->_recurse_cond($cond, $combining_count) },
85             HASHREF => sub { $self->_recurse_cond($cond, $combining_count) },
86             UNDEF => sub { croak "not supported : UNDEF in arrayref" },
87             SCALAR => sub { $self->_recurse_cond( { $cond => shift(@cp_conds) } , $combining_count ) },
88             });
89             push @statment, @child_statment;
90             $combining_count = $child_combining_count;
91             }
92             print STDERR "#OUT _cond_ARRAYREF $conds $combining_count\n" if $TRACE > 9 ;
93             return ( $combining_count, @statment );
94             }
95              
96             sub _cond_HASHREF {
97             my $self = shift;
98             my $cond = shift;
99             my $combining_count = shift || 0;
100             print STDERR "#IN _cond_HASHREF $cond $combining_count\n" if $TRACE > 9 ;
101             my @all_statment = ();
102             my $child_combining_count = 0;
103             my @child_statment = ();
104              
105             foreach my $key ( keys %{ $cond } ){
106             my $value = $cond->{$key};
107             my $method ;
108              
109             if ( $key =~ /^-/ ){
110             # Child key for combining filters ( -and / -or )
111             ( $child_combining_count, @child_statment ) = $self->_cond_op_in_hash($key, $value, $combining_count);
112             $combining_count = $child_combining_count;
113             } else{
114             $method = $self->_METHOD_FOR_refkind("_cond_hashpair",$value);
115             ( $child_combining_count, @child_statment ) = $self->$method($key, $value, undef ,$combining_count);
116             $combining_count = $child_combining_count;
117             }
118              
119             push @all_statment, @child_statment;
120             }
121             print STDERR "#OUT _cond_HASHREF $cond $combining_count\n" if $TRACE > 9;
122             return ( $combining_count, @all_statment );
123             }
124              
125             sub _cond_hashpair_UNDEF {
126             my $self = shift;
127             my $key = shift || '';
128             my $value = shift;
129             my $operator = shift || '=';
130             print STDERR "# _cond_hashpair_UNDEF\n" if $TRACE > 9 ;
131              
132             my $combining_count = shift || 0;
133             my @statment = (
134             sprintf("%s: %s %s",$self->mode,$key,$operator)
135             );
136             $combining_count++;
137             return ( $combining_count, @statment );
138             };
139              
140             sub _cond_hashpair_SCALAR {
141             my $self = shift;
142             my $key = shift || '';
143             my $value = shift;
144             my $operator = shift || '=';
145             print STDERR "# _cond_hashpair_SCALAR\n" if $TRACE > 9 ;
146              
147             my $combining_count = shift || 0;
148             my @statment = (
149             sprintf("%s: %s %s %s",$self->mode,$key,$operator,$value)
150             );
151             $combining_count++;
152             return ( $combining_count, @statment );
153             };
154              
155             sub _cond_hashpair_ARRAYREF {
156             my $self = shift;
157             my $key = shift || '';
158             my $values = shift || [];
159             my $operator = shift || '=';
160             my $combining_count = shift || 0;
161             print STDERR "#IN _cond_hashpair_ARRAYREF $combining_count\n" if $TRACE > 9;
162              
163             my @statment = ();
164             foreach my $value ( @{ $values }){
165             push @statment, sprintf("%s: %s %s %s",$self->mode,$key,$operator,$value);
166             $combining_count++;
167             }
168             print STDERR "#OUT _cond_hashpair_ARRAYREF $combining_count\n" if $TRACE > 9;
169             return ( $combining_count, @statment );
170             }
171              
172             sub _cond_hashpair_HASHREF {
173             my $self = shift;
174             my $key = shift || '';
175             my $values = shift || {};
176             my $combining = shift || undef;
177             my $combining_count = shift || 0;
178              
179             print STDERR "#IN Abstract::_cond_hashpair_HASHREF $combining_count\n" if $TRACE > 9;
180             my @statment = ();
181              
182             foreach my $child_key ( keys %{ $values } ){
183             my $child_value = $values->{ $child_key };
184              
185             if ( $child_key =~ /^-/ ){
186             my ( $child_combining_count, @child_statment ) = $self->_cond_op_in_hash($child_key, { $key => $child_value } , 0);
187             $combining_count += $child_combining_count;
188             push @statment, @child_statment;
189             } elsif ( $child_key =~ /^[!<>=~]/ ){
190             # Child key is a operator like:
191             # = equality
192             # ~ match regular expression (substring match)
193             # =~ equality ignoring case
194             # ~~ regular expression ignoring case
195             # < less than
196             # > greater than
197             # <= less or equal
198             # >= greater or equal
199             my $method = $self->_METHOD_FOR_refkind("_cond_hashpair",$child_value);
200             my ( $child_combining_count, @child_statment ) = $self->$method($key, $child_value,$child_key);
201             $combining_count += $child_combining_count;
202             push @statment, @child_statment;
203             } else {
204             my $method = $self->_METHOD_FOR_refkind("_cond_hashpair",$child_value);
205             my ( $child_combining_count, @child_statment ) = $self->$method($key, $child_value);
206             $combining_count += $child_combining_count;
207             push @statment, @child_statment;
208             }
209             }
210             print STDERR "#OUT Abstract::_cond_hashpair_HASHREF $combining_count\n" if $TRACE > 9;
211             return ( $combining_count, @statment );
212             }
213              
214             sub _cond_op_in_hash {
215             my $self = shift;
216             my $operator = shift;
217             my $value = shift;
218             my $combining_count = shift;
219             print STDERR "#IN _cond_op_in_hash $operator $value $combining_count\n" if $TRACE > 9;
220              
221             if ( defined $operator and $operator =~ /^-/ ){
222             $operator =~ s/^-//; # remove -
223             $operator =~ s/^\s+|\s+$//g; # remove leading/trailing space
224             $operator = 'GroupBy' if ( $operator eq 'Groupby' );
225             }
226              
227             my $operator_config = first { $operator =~ $_->{regexp} } @{ $self->operators };
228             my $operator_handler = $operator_config->{handler};
229             if ( not ref $operator_handler ){
230             return $self->$operator_handler($operator,$value,$combining_count);
231             }elsif ( ref $operator_handler eq 'CODE' ) {
232             return $operator_handler->($self,$operator,$value,$combining_count);
233             }
234              
235             print STDERR "#OUT _cond_op_in_hash $operator $value $combining_count\n" if $TRACE > 9;
236             return ( 0, () );
237             }
238             sub _cond_compining {
239             my $self = shift;
240             my $combining = shift;
241             my $value = shift;
242             my $combining_count = shift || 0;
243             print STDERR "#IN _cond_compining $combining $combining_count\n" if $TRACE > 9;
244             $combining_count++;
245             my @statment = ();
246              
247             if ( defined $combining and $combining =~ /^-/ ){
248             $combining =~ s/^-//; # remove -
249             $combining =~ s/^\s+|\s+$//g; # remove leading/trailing space
250             $combining = ucfirst( $combining );
251             }
252             my ( $child_combining_count, @child_statment )= $self->_recurse_cond($value, 0 );
253             push @statment, @child_statment;
254             if ( defined $combining ) {
255             push @statment, sprintf("%s%s: %d",
256             $self->compining_prefix,
257             ucfirst( $combining ),
258             $child_combining_count,
259             );
260             }
261             print STDERR "#OUT _cond_compining $combining $combining_count \n" if $TRACE > 9;
262             return ( $combining_count, @statment );
263             }
264              
265             sub _refkind {
266             my ($self, $data) = @_;
267             my $suffix = '';
268             my $ref;
269             my $n_steps = 0;
270              
271             while (1) {
272             # blessed objects are treated like scalars
273             $ref = (blessed $data) ? '' : ref $data;
274             $n_steps += 1 if $ref;
275             last if $ref ne 'REF';
276             $data = $$data;
277             }
278              
279             my $base = $ref || (defined $data ? 'SCALAR' : 'UNDEF');
280              
281              
282             return $base . ('REF' x $n_steps);
283             }
284              
285             sub _dispatch_refkind {
286             my $self = shift;
287             my $value = shift;
288             my $dispatch_table = shift;
289              
290             my $type = $self->_refkind($value);
291             my $coderef = $dispatch_table->{$type};
292              
293             die sprintf("No coderef for %s ( %s ) found!",$value, $type)
294             unless ( ref $coderef eq 'CODE' );
295              
296             return $coderef->();
297             }
298              
299             sub _METHOD_FOR_refkind {
300             my $self = shift;
301             my $prefix = shift || '';
302             my $value = shift;
303             my $type = $self->_refkind( $value );
304             my $method = sprintf("%s_%s",$prefix,$type);
305             return $method;
306             }
307              
308              
309              
310             1;
311             __END__
312             =head1 NAME
313              
314             Monitoring::Livestatus::Class::Base::Abstract - Base class to generate
315             livestatus statments
316              
317             =head2 SYNOPSIS
318              
319             =head1 ATTRIBUTES
320              
321             =head2 ctx
322              
323             Reference to context object L<Monitoring::Livestatus::Class>
324              
325             =head2 mode
326              
327             =head2 compining_prefix
328              
329             =head1 METHODS
330              
331             =head2 apply
332              
333             Example usage:
334              
335             my $filter_obj = Monitoring::Livestatus::Class::Abstract::...->new();
336             $filter_obj->apply( { name => 'localhost' } );
337             $filter_obj->apply( { name => [ 'localhost', 'gateway' ] } );
338             $filter_obj->apply( [ { name => 'localhost' }, { name => 'gateway' } ] );
339              
340             Returns: @statments|\@statments
341              
342             =head1 INTERNAL METHODS
343              
344             =over 4
345              
346             =item build_mode
347              
348             =item build_compining_prefix
349              
350             =item build_operators
351              
352             =item _execute
353              
354             =item _recurse_cond
355              
356             =item _cond_UNDEF
357              
358             =item _cond_ARRAYREF
359              
360             =item _cond_HASHREF
361              
362             =item _cond_hashpair_SCALAR
363              
364             =item _cond_hashpair_ARRAYREF
365              
366             =item _cond_hashpair_HASHREF
367              
368             =item _refkind
369              
370             =item _dispatch_refkind
371              
372             =item _METHOD_FOR_refkind
373              
374             =back
375              
376             =head1 AUTHOR
377              
378             See L<Monitoring::Livestatus::Class/AUTHOR> and L<Monitoring::Livestatus::Class/CONTRIBUTORS>.
379              
380             =head1 COPYRIGHT & LICENSE
381              
382             Copyright 2009 Robert Bohne.
383              
384             This program is free software; you can redistribute it and/or modify it
385             under the terms of either: the GNU General Public License as published
386             by the Free Software Foundation; or the Artistic License.
387              
388             See http://dev.perl.org/licenses/ for more information.
389              
390             =cut