package Lire::Report::Entry;
use strict;
use Carp;
use Lire::Utils qw/ xml_encode check_object_param /;
use Lire::Report::Group;
=pod
=head1 NAME
Lire::Report::Entry - Interface to subreport's data.
=head1 SYNOPSIS
foreach my $name ( $entry->names() ) {
print "Name: ", $name->{'content'}, "\n";
}
foreach my $value ( $entry->values() ) {
if ( ref $value eq 'Lire::Report::Group' ) {
# Value is a group
foreach my $e ( $value->entries() ) {
print_entry( $e );
}
} else {
print "Value: ", $value->{'content'}, "\n";
}
}
=head1 DESCRIPTION
The Lire::Report::Entry objects are used to hold the subreport's data.
=head1 CONSTRUCTOR
One creates a new Entry object by using the create_entry method on a
Lire::Report::Subreport or Lire::Report::Group object. Use the add_name(),
create_group() and add_value() methods to fill the entry.
=cut
sub new {
my ( $class, $group ) = @_;
check_object_param( $group, 'group', 'Lire::Report::Group' );
return bless( {'data' => [],
'group' => $group},
$class );
}
=pod
=head1 OBJECT METHODS
=head2 row_idx()
Returns the row index in the table body where this entry's data should
be displayed. If undef, this entry shouldn't be displayed.
=cut
sub row_idx {
$_[0]{'row_idx'} = $_[1] if @_ == 2;
return $_[0]{'row_idx'};
}
=pod
=head2 subreport()
Returns the Lire::Report::Subreport object in which this entry is contained.
=cut
sub subreport {
my $self = $_[0];
my $parent = $self->group();
while ( $parent && $parent->parent_entry() ) {
$parent = $parent->parent_entry()->group();
}
return $parent;
}
=pod
=head2 group()
Returns the Lire::Report::Group object which contains this entry.
=cut
sub group {
return $_[0]{'group'};
}
=pod
=head2 group_info()
Returns the Lire::Report::GroupInfo which contains the information
related to the group in which this entry is.
=cut
sub group_info {
return $_[0]{'group'}->group_info();
}
=pod
=head2 data()
Returns as an array the data contained in this entry. This is a list
of hashes or Lire::Report::Group object.
=cut
sub data {
return @{$_[0]->{'data'}};
}
=pod
=head2 data_by_name( $name )
Returns the data item contained in this Entry that was generated by
the operator named $name. Returns undef if no such data item can be
found.
=cut
sub data_by_name {
my ( $self, $name ) = @_;
foreach my $d ( @{$self->{'data'}} ) {
if ( UNIVERSAL::isa( $d, 'Lire::Report::Group' ) ) {
return $d if $d->group_info()->name() eq $name;
} else {
return $d if $d->{'col_info'}->name() eq $name;
}
}
return undef;
}
=pod
=head2 names()
Returns the names of the entry. This is an array of hashes. The name's
hash contains the following keys:
=over 4
=item type
Always set to 'name'.
=item content
That's the actual content of the name element. This contains the name
in a format suitable for display.
=item value
This contains the unformatted value of the name. For example, when the
name is a time string, this attribute will contains the time in
seconds since epoch.
=item missing_cases
This value contains the number of DLF records which had a undefined
value in one of the required fields to compute this statistic.
=item range
For some names, the actual content express a range (time, size, etc.).
This attribute contains the length of the range.
=item col_info
The Lire::Report::ColumnInfo object describing this name.
=back
=cut
sub names {
return grep { $_->{'type'} eq 'name' } @{$_[0]->{'data'}};
}
=pod
=head2 add_name( $content, [$value], [$range] )
Adds a new name to this entry. Consult the documentation of the
names() method for a description of the meaning of the various
parameters which have the same meaning as the keys with the same
name.
The names, values and groups should be added in the order specified by
this entry's GroupInfo. You'll get an exception otherwise.
=cut
sub add_name {
my ( $self, $content, $value, $range ) = @_;
$content = '' unless defined $content;
$value = $content unless defined $value;
my $idx = $#{$self->{'data'}} + 1;
my $info = $self->group_info->info_by_index( $idx );
check_object_param( $info, "Data_$idx", 'Lire::Report::ColumnInfo' );
my %n = ('type' => 'name',
'content' => $content,
'value' => $value,
'col_info' => $info);
$n{'range'} = $range if defined $range;
push @{$self->{'data'}}, \%n;
return;
}
=pod
=head2 values()
Returns the values of the entry. This is an array of hashes or objects.
If the value is an hash, it has the following keys:
=over 4
=item type
Always set to 'value'.
=item content
That's the actual content of the value element. This contains the
value in a format suitable for display.
=item value
This contains the unformatted value. For example, when bytes are
displayed using "1M" or "1.1G", this will contain the value in single bytes.
=item missing_cases
The number of DLF records which had an undefined value in one of
fields required by this operator.
=item total
This is used by values that represent an average. It contains the
total which makes up the average.
=item n
This is used by values that represent an average. It contains the
total which was used in the division to compute the average.
=item col_info
The Lire::Report::ColumnInfo object describing this value.
=back
=cut
sub values {
return grep { $_->{'type'} eq 'value' } @{$_[0]->{'data'}};
}
=pod
=head2 groups()
Returns in an array the Lire::Report::Group contained in this Entry.
=cut
sub groups {
return grep { UNIVERSAL::isa( $_, 'Lire::Report::Group' ) }
@{$_[0]->{'data'}};
}
=pod
=head2 create_group()
Creates a new group for this entry. This will also append it
to this entry data. If you create the group out of order compared to
the names and values that should go in that entry, you'll get an
exception.
=cut
sub create_group {
my $self = $_[0];
my $idx = $#{$self->{'data'}} + 1;
my $info = $self->group_info->info_by_index( $idx );
check_object_param( $info, "Data_$idx", 'Lire::Report::GroupInfo' );
my $group = new Lire::Report::Group( $self, $info );
push @{$self->{'data'}}, $group;
return $group;
}
=pod
=head2 add_value( %value )
Adds a new value to this entry. The value hash should at least
contains the 'content' key. It can also includes values for the 'n',
'total' and 'missing_cases' keys. Consult the documentation of the
values() method for a description of the meaning of the various
parameters: these have the same meaning as the keys with the same
names.
The names, values and groups should be added in the order specified by
this entry's GroupInfo. You'll get an exception otherwise.
=cut
sub add_value {
my $self = $_[0];
my $value = ref( $_[1] ) ? $_[1] : { @_[1..$#_] };
$value->{'content'} = "" unless defined $value->{'content'};
$value->{'value'} = $value->{'content'} unless defined $value->{'value'};
my $idx = $#{$self->{'data'}} + 1;
my $info = $self->group_info()->info_by_index( $idx );
check_object_param( $info, "Data_$idx", 'Lire::Report::ColumnInfo' );
$value->{'type'} = 'value';
$value->{'col_info'} = $info;
$value->{'n'} = undef
unless exists $value->{'n'};
$value->{'total'} = undef
unless exists $value->{'total'};
$value->{'missing_cases'} = 0
unless defined $value->{'missing_cases'};
push @{$self->{'data'}}, $value;
return;
}
#
# helper method for Lire::Report::Subreport::last_row_idx()
#
sub _last_row_idx {
my $self = $_[0];
return undef unless defined $self->{'row_idx'};
my $last = $self->{'row_idx'};
foreach my $group ( $self->groups() ) {
my $group_last = $group->_last_row_idx();
$last = $group_last
if defined $group_last && $group_last > $last;
}
return $last;
}
#
# helper method for Lire::Report::Subreport::getrow_by_idx()
#
sub _getrow_by_idx {
my ( $self, $idx, $row ) = @_;
if ( $self->{'row_idx'} == $idx ) {
foreach my $item ( @{$self->{'data'}} ) {
my @cells = ( UNIVERSAL::isa( $item, 'Lire::Report::Group' )
? $item->summary_values()
: $item );
foreach my $cell ( @cells ) {
$row->[$cell->{'col_info'}->col_start()] = $cell;
}
}
} else {
foreach my $group ( $self->groups() ) {
$group->_getrow_by_idx( $idx, $row );
}
}
}
#------------------------------------------------------------------------
# Method write_report( $fh, $indent )
#
sub write_report {
my ( $self, $fh, $indent ) = @_;
$fh ||= *STDOUT;
my $pfx = ' ' x $indent;
print $fh $pfx, "<lire:entry";
print $fh qq{ row-idx="$self->{'row_idx'}"}
if defined $self->row_idx();
print $fh ">\n";
foreach my $d ( @{$self->{'data'}} ) {
if ( $d->{'type'} eq 'name' ) {
write_name( $fh, $pfx, $d );
} elsif ( $d->{'type'} eq 'value' ) {
write_value( $fh, $pfx, $d );
} else {
# Group
$d->write_report( $fh, $indent + 1 );
}
}
print $fh "$pfx</lire:entry>\n";
return;
}
#------------------------------------------------------------------------
# Function write_name( $fh, $pfx, $d )
#
# Writes $d into a lire:name element.
sub write_name {
my ( $fh, $pfx, $d ) = @_;
print $fh $pfx, ' <lire:name col="', $d->{'col_info'}->name(), '"';
print $fh ' value="', xml_encode( $d->{'value'} ), '"',
if $d->{'value'} ne $d->{'content'};
print $fh qq! range="$d->{'range'}"!
if defined $d->{'range'};
print $fh ">", xml_encode( $d->{'content'} ), "</lire:name>\n";
return;
}
#------------------------------------------------------------------------
# Function write_value($fh, $pfx, $d)
#
# Writes $d into a lire:value element.
sub write_value {
my ( $fh, $pfx, $d ) = @_;
print $fh $pfx, ' <lire:value col="', $d->{'col_info'}->name(), '"',
' missing-cases="', $d->{'missing_cases'}, '"';
print $fh qq! total="$d->{'total'}"!
if defined $d->{'total'};
print $fh qq! n="$d->{'n'}"!
if defined $d->{'n'};
print $fh qq! value="$d->{'value'}"!
if $d->{'value'} ne $d->{'content'};
print $fh ">$d->{'content'}</lire:value>\n";
return;
}
#------------------------------------------------------------------------
# Method delete()
#
# Remove circular references
sub delete {
my $self = $_[0];
foreach my $g ( grep { $_->{'type'} eq 'group' } $self->values() ) {
$g->delete();
}
%$self = ();
return;
}
# keep perl happy
1;
=pod
=head1 SEE ALSO
Lire::ReportParser::ReportBuilder(3pm) Lire::Report(3pm)
Lire::Report::Subreport(3pm) Lire::Report::Section(3pm)
Lire::Report::Group(3pm)
=head1 VERSION
$Id: Entry.pm,v 1.32 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 <flacoste@logreport.org>
=cut
syntax highlighted by Code2HTML, v. 0.9.1