package Lire::Report::TableInfo;
use strict;
use base qw/ Lire::Report::GroupInfo /;
use Lire::Config::Index;
use Lire::Config::VariableIndex;
use Carp;
=pod
=head1 NAME
Lire::Report::TableInfo - Object that holds all the GroupInfo and ColumnInfo for one subreport
=head1 SYNOPSIS
my $info = $subreport->table_info;
my $col_info = $info->colum_info( "request_total" );
=head1 DESCRIPTION
The Lire::Report::TableInfo object holds the ColumnInfo and GroupInfo
objects for one subreport..
=head1 CONSTRUCTOR
=head2 new()
Creates a new Lire::Report::TableInfo object.
=cut
sub new {
my $self = bless( {'name' => "table",
'children' => [],
'row_idx' => 0,
'parent' => undef},
$_[0] );
$self->index( 0 );
return $self;
}
=pod
=head2 column_info_by_name( $name )
Returns the Lire::Report::ColumnInfo object that has the name $name.
Contrary to the method in Lire::Report::GroupInfo, this one will
throw an exception if there is no column named $name.
=cut
sub column_info_by_name {
my ( $self, $name ) = @_;
my $col = $self->SUPER::column_info_by_name( $name );
croak "There is no column named $name"
unless $col;
return $col;
}
=pod
=head2 column_info_by_col_start( $idx )
Returns the Lire::Report::ColumnInfo object that is starts at column
index $idx.
Contrary to the method in Lire::Report::GroupInfo, this one will throw
an exception if this column is out of bounds.
=cut
sub column_info_by_col_start {
my ( $self, $idx ) = @_;
my $col = $self->SUPER::column_info_by_col_start( $idx );
croak "There is no column index $idx"
unless $col;
return $col;
}
=pod
=head2 group_info( $name )
Returns the Lire::Report::GroupInfo object that has the name $name.
Contrary to the method in Lire::Report::GroupInfo, this one will
throw an exception if there is no column named $name.
=cut
sub group_info {
my ( $self, $name ) = @_;
# Cache the result of the base lookup
unless ( exists $self->{'group_info'}{$name} ) {
$self->{'group_info'}{$name} = $self->SUPER::group_info( $name );
}
croak "There is no group named $name"
unless $self->{'group_info'}{$name};
return $self->{'group_info'}{$name};
}
=pod
=head2 ncols()
Returns the number of columns there is in this table.
=cut
sub ncols {
my $self = $_[0];
my @cols = $self->column_infos();
return scalar @cols;
}
=pod
=head2 column_infos()
Returns an array containing all the columns of the table. Each element
is a Lire::Report::ColumnInfo object.
=cut
sub column_infos {
my $self = $_[0];
my @cols = $self->column_children();
my @groups = $self->group_children();
while ( @groups ) {
my $g = shift @groups;
push @cols, $g->column_children();
push @groups, $g->group_children();
}
return sort { $a->col_start() <=> $b->col_start() } @cols;
}
=pod
=head2 groups()
Returns an array containing all the groups of the table. Each element
is a Lire::Report::GroupInfo object.
=cut
sub groups {
my $self = $_[0];
my @groups = ( $self );
my @children = ( $self );
while ( @children ) {
my $g = shift @children;
push @groups, $g->group_children();
push @children, $g->group_children();
}
return @groups;
}
=pod
=head2 columns_width()
Returns an array where each element represents the suggested columns'
width in characters.
=cut
sub columns_width {
return map { $_->col_width() } $_[0]->columns();
}
=pod
=head2 header_rows()
Returns an array reference containing one array reference for each rows
in the header. Each row contains the ColumnInfo that should appear
on the header line. The first row contains all the numerical columns and
the categorical columns appear based on their nesting. The indices of the
column is always equals to its column's start.
=cut
sub header_rows {
my $self = $_[0];
my $rows = [];
my @groups = $self->groups();
my @group_row;
my $ncols = $self->ncols();
while ( @group_row = grep { $_->row_idx() == ( $#$rows + 1 ) } @groups ) {
# Grab the ColumInfo in that row
my @cols = ();
foreach my $g ( @group_row ) {
push @cols, grep { $_->class() eq 'categorical' } $g->column_children();
# Special case for the first row, all value columns go there
push @cols, grep { $_->class eq 'numerical' } $self->column_infos()
unless @$rows;
}
my $row = [ (undef) x $ncols ];
foreach my $col ( @cols ) {
$row->[ $col->col_start() ] = $col;
}
push @$rows, $row;
}
return $rows;
}
=pod
=head2 set_variables_indices()
Registers this TableInfo's variables using Lire::Config::VariableIndex.
=cut
sub set_variables_indices {
my $self = $_[0];
Lire::Config::Index->set_index( 'variables',
new Lire::Config::VariableIndex( $self, 'both' ) );
Lire::Config::Index->set_index( 'categorical_variables',
new Lire::Config::VariableIndex( $self, 'categorical' ) );
Lire::Config::Index->set_index( 'numerical_variables',
new Lire::Config::VariableIndex( $self, 'numerical' ) );
return;
}
=pod
=head2 reset_variable_indices()
Removes the variables indices. This can be called to undo the effect
of set_variables_indices().
=cut
sub reset_variables_indices {
my $self = $_[0];
Lire::Config::Index->set_index( 'variables', undef );
Lire::Config::Index->set_index( 'categorical_variables', undef );
Lire::Config::Index->set_index( 'numerical_variables', undef );
return;
}
# ------------------------------------------------------------------------
# Method compute_columns_width()
#
# Try to determine the width of all the columns
sub compute_columns_width {
my $self = $_[0];
$self->assign_columns_width;
$self->correct_spanning_column_width( $self );
return;
}
#-----------------------------------------------------------------------
# Methods write_report( $fh, $index )
sub write_report {
my ( $self, $fh, $indent ) = @_;
$fh ||= *STDOUT;
my $pfx = ' ' x $indent;
print $fh $pfx, qq{\n};
foreach my $i ( @{$self->{'children'}} ) {
$i->write_report( $fh, $indent + 1 );
}
print $fh $pfx, "\n";
return;
}
# keep perl happy
1;
__END__
=pod
=head1 SEE ALSO
Lire::Report::Subreport(3pm) Lire::Report::ColumnInfo(3pm)
=head1 VERSION
$Id: TableInfo.pm,v 1.26 2006/07/23 13:16:31 vanbaal Exp $
=head1 COPYRIGHT
Copyright (C) 2002 Stichting LogReport Foundation LogReport@LogReport.org
This file is part of Lire.
Lire is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program (see COPYING); if not, check with
http://www.gnu.org/copyleft/gpl.html.
=head1 AUTHOR
Francis J. Lacoste
=cut