File Coverage

blib/lib/Siebel/Srvrmgr/ListParser/Output/Tabular.pm
Criterion Covered Total %
statement 22 23 95.6
branch n/a
condition n/a
subroutine 8 9 88.8
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1             package Siebel::Srvrmgr::ListParser::Output::Tabular;
2              
3             =pod
4              
5             =head1 NAME
6              
7             Siebel::Srvrmgr::ListParser::Output::Tabular - base class for all command outputs that have a tabular form
8              
9             =cut
10              
11 25     25   23930 use Moose;
  25         339837  
  25         180  
12 25     25   167094 use namespace::autoclean;
  25         8389  
  25         235  
13 25     25   1936 use Carp qw(cluck);
  25         66  
  25         2587  
14 25     25   1318 use Siebel::Srvrmgr::Regexes qw(ROWS_RETURNED);
  25         61  
  25         1237  
15 25     25   5356 use Siebel::Srvrmgr::Types;
  25         65  
  25         778  
16 25     25   18605 use Siebel::Srvrmgr::ListParser::Output::Tabular::Struct::Fixed;
  25         8489  
  25         1133  
17 25     25   22712 use Siebel::Srvrmgr::ListParser::Output::Tabular::Struct::Delimited;
  25         8789  
  25         21183  
18              
19             extends 'Siebel::Srvrmgr::ListParser::Output';
20              
21             with 'Siebel::Srvrmgr::ListParser::Output::ToString';
22              
23             =head1 SYNOPSIS
24              
25             This is a base class, look for implementations of subclasses for examples.
26              
27             =head1 DESCRIPTION
28              
29             This class is a base class for all classes that parses output that have a tabular form (almost all of them).
30              
31             All those outputs have a header with the columns names and the columns with the data. The "columns" are defined by a single character to separate them or by fixed width.
32              
33             It have common attributes and methods for parsing different commands output.
34              
35             This class extends L<Siebel::Srvrmgr::ListParser::Output> and applies the Moose Role L<Siebel::Srvrmgr::ListParser::Output::ToString>.
36              
37             =head1 ATTRIBUTES
38              
39             =head2 structure_type
40              
41             Identifies which subtype of output a instance is. See L<Siebel::Srvrmgr::Types>, C<OutputTabularType> for details.
42              
43             It is a read-only, required attribute during object creation.
44              
45             =cut
46              
47             has structure_type => (
48             is => 'ro',
49             isa => 'OutputTabularType',
50             reader => 'get_type',
51             required => 1
52             );
53              
54             =head2 col_sep
55              
56             The column/field separator in the tabular output, if any. Used to parse the data into columns.
57              
58             It is a single character (see L<Siebel::Srvrmgr::Types>, C<Chr>) and is a read-only, required attribute during object creation.
59              
60             =cut
61              
62             has col_sep => (
63             is => 'ro',
64             isa => 'Chr',
65             reader => 'get_col_sep'
66             );
67              
68             =head2 expected_fields
69              
70             An array reference with the fields names expected by a subclass.
71              
72             It is used for validation and parsing of the output. If the output doesn't have the same sequence of fields names,
73             an exception will be raised.
74              
75             It is a read-only, required attribute during object creation.
76              
77             =cut
78              
79             has expected_fields => (
80             is => 'ro',
81             isa => 'ArrayRef',
82             reader => 'get_expected_fields',
83             writer => '_set_expected_fields',
84             builder => '_build_expected',
85             lazy => 1
86             );
87              
88             =head2 known_types
89              
90             The two known types of tabular output, by default:
91              
92             =over
93              
94             =item *
95              
96             L<Siebel::Srvrmgr::ListParser::Output::Tabular::Struct::Fixed>
97              
98             =item *
99              
100             L<Siebel::Srvrmgr::ListParser::Output::Tabular::Struct::Delimited>
101              
102             =back
103              
104             Unless you're going to subclass this class you won't need to know more than that.
105              
106             =cut
107              
108             has known_types => (
109             is => 'ro',
110             isa => 'HashRef[Str]',
111             reader => 'get_known_types',
112             default => sub {
113             {
114             fixed =>
115             'Siebel::Srvrmgr::ListParser::Output::Tabular::Struct::Fixed',
116             delimited =>
117             'Siebel::Srvrmgr::ListParser::Output::Tabular::Struct::Delimited'
118             };
119             }
120             );
121              
122             =head2 found_header
123              
124             A boolean indicating if the header was located in the command output.
125              
126             Returns true or false depending on it. By default is false.
127              
128             =cut
129              
130             has found_header => (
131             is => 'ro',
132             isa => 'Bool',
133             reader => 'found_header',
134             writer => '_set_found_header',
135             default => 0
136             );
137              
138             =head1 METHODS
139              
140             =head2 get_type
141              
142             Getter for C<structure_type> attribute.
143              
144             =head2 get_col_sep
145              
146             Getter for C<col_sep> attribute.
147              
148             =head2 get_expected_fields
149              
150             Getter for C<expected_fields> attribute.
151              
152             =head2 found_header
153              
154             Getter for C<found_header> attribute.
155              
156             =cut
157              
158             sub _build_expected {
159              
160 2     2   27 confess
161             '_build_expected must be overrided by subclasses of Siebel::Srvrmgr::Output::Tabular';
162              
163             }
164              
165             sub _consume_data {
166              
167 0     0     confess
168             '_consume_data must be overrided by subclasses of Siebel::Srvrmgr::ListParser::Output::Tabular';
169              
170             }
171              
172             =head2 parse
173              
174             The method that parses the content of C<raw_data> attribute.
175              
176             This method expects a header in the file, so all subclasses of this class.
177              
178             =cut
179              
180             override 'parse' => sub {
181              
182             my $self = shift;
183              
184             my $data_ref = $self->get_raw_data();
185              
186             confess 'Invalid data to parse'
187             unless ( ( ( ref($data_ref) ) eq 'ARRAY' )
188             and ( scalar( @{$data_ref} ) ) );
189              
190             # cleaning up, state machine should not handle the end of response from a list command
191             while (
192             ( scalar( @{$data_ref} ) > 0 )
193             and ( ( $data_ref->[ $#{$data_ref} ] eq '' )
194             or ( $data_ref->[ $#{$data_ref} ] =~ ROWS_RETURNED ) )
195             )
196             {
197              
198             pop( @{$data_ref} );
199              
200             }
201              
202             confess 'Raw data became invalid after initial cleanup'
203             unless ( @{$data_ref} );
204              
205             my $struct;
206              
207             SWITCH: {
208              
209             if ( ( $self->get_type eq 'delimited' ) and $self->get_col_sep() ) {
210              
211             $struct = $self->get_known_types()->{ $self->get_type() }->new(
212             {
213             header_cols => $self->get_expected_fields(),
214             col_sep => $self->get_col_sep()
215             }
216             );
217              
218             last SWITCH;
219              
220             }
221              
222             if ( $self->get_type() eq 'fixed' ) {
223              
224             $struct = $self->get_known_types()->{ $self->get_type() }
225             ->new( { header_cols => $self->get_expected_fields() } );
226              
227             }
228             else {
229              
230             confess "Don't know what to do with "
231             . $self->get_type()
232             . ' and column separator = '
233             . $self->get_col_sep();
234              
235             }
236              
237             }
238              
239             my $header = $struct->get_header_regex();
240             my $header_regex = qr/$header/;
241             my %parsed_lines;
242             my $line_header_regex = qr/^\-+\s/;
243              
244             foreach my $line ( @{$data_ref} ) {
245              
246             SWITCH: {
247              
248             if ( $line eq '' ) {
249              
250             # do nothing
251             last SWITCH;
252             }
253              
254             if ( $line =~ $line_header_regex )
255             { # this is the '-------' below the header
256              
257             confess 'could not defined fields pattern'
258             unless ( $struct->define_fields_pattern($line) );
259             last SWITCH;
260              
261             }
262              
263             # this is the header
264             if ( $line =~ $header_regex ) {
265              
266             $self->_set_found_header(1);
267             last SWITCH;
268              
269             }
270             else {
271              
272             my $fields_ref = $struct->get_fields($line);
273              
274             confess "Cannot continue without having fields pattern defined"
275             unless ( ( defined($fields_ref) ) and ( @{$fields_ref} ) );
276              
277             unless ( $self->_consume_data( $fields_ref, \%parsed_lines ) ) {
278              
279             confess 'Could not parse fields from line [' . $line . ']';
280              
281             }
282              
283             }
284              
285             }
286              
287             }
288              
289             confess 'failure detected while parsing: header not found'
290             unless ( $self->found_header() );
291              
292             $self->set_data_parsed( \%parsed_lines );
293             $self->set_raw_data( [] );
294              
295             return 1;
296              
297             };
298              
299             =head1 CAVEATS
300              
301             All subclasses of Siebel::Srvrmgr::ListParser::Output::Tabular are expect to have both the header and trailer in the output of executed commands in C<srvrmgr>
302             program. Removing one or both of them will result in parsing errors and probably exceptions.
303              
304             =head1 SEE ALSO
305              
306             =over
307              
308             =item *
309              
310             L<Siebel::Srvrmgr::ListParser::Output>
311              
312             =item *
313              
314             l<Siebel::Srvrmgr::ListParser::Output::ToString>
315              
316             =back
317              
318             =head1 AUTHOR
319              
320             Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>.
321              
322             =head1 COPYRIGHT AND LICENSE
323              
324             This software is copyright (c) 2012 of Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>.
325              
326             This file is part of Siebel Monitoring Tools.
327              
328             Siebel Monitoring Tools is free software: you can redistribute it and/or modify
329             it under the terms of the GNU General Public License as published by
330             the Free Software Foundation, either version 3 of the License, or
331             (at your option) any later version.
332              
333             Siebel Monitoring Tools is distributed in the hope that it will be useful,
334             but WITHOUT ANY WARRANTY; without even the implied warranty of
335             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
336             GNU General Public License for more details.
337              
338             You should have received a copy of the GNU General Public License
339             along with Siebel Monitoring Tools. If not, see L<http://www.gnu.org/licenses/>.
340              
341             =cut
342              
343             __PACKAGE__->meta->make_immutable;
344