package Lire::ReportParser::ReportBuilder;

use strict;

use vars qw/ $VERSION @ISA /;

use Lire::ReportParser;

use Lire::Report;
use Lire::Report::Entry;
use Lire::Report::Group;
use Lire::Report::Image;
use Lire::Report::Section;
use Lire::Report::Subreport;

use Carp;

BEGIN {
    ($VERSION)	= '$Revision: 1.7 $' =~ m!Revision: ([.\d]+)!;
    @ISA = qw/ Lire::ReportParser /;
}

sub new {
    my $proto = shift;
    my $class = ref( $proto) || $proto;

    my $self = $class->SUPER::new( @_, all_entries => 1 );
    my %args = @_;
    $self->{only_head} = $args{only_head};

    $self;
}

sub parse_start {
    my ( $self ) = @_;

    $self->{report} = bless {
			     descriptions => [],
			     sections	  => [],
			     generator	  => __PACKAGE__ . "(3pm)",
			    }, "Lire::Report";

    $self->{curr_section} = undef;
    $self->{curr_subreport} = undef;
    $self->{curr_group} = undef;
    $self->{curr_entry} = undef;
    $self->{curr_image} = undef;
    $self->{curr_desc}  = undef;
}

sub parse_end {
    my ( $self ) = @_;

    return $self->{report};
}

sub report_start {
    my ( $self, %attr ) = @_;

    $self->SUPER::report_start( %attr );

    $self->{report}{version} = $attr{version};
    $self->{report}{superservice} = $attr{superservice};
}

sub handle_title {
    my ( $self, $title ) = @_;

    if ( $self->{curr_image} ) {
	$self->{curr_image}{title} = $title;
    } elsif ( $self->{curr_subreport} ) {
	$self->{curr_subreport}{title} = $title;
    } elsif ( $self->{curr_section} ) {
	$self->{curr_section}{title} = $title;
    } else {
	$self->{report}{title} = $title;
    }
}

sub handle_date {
    my ( $self, $date, $date_epoch ) = @_;

    if ( $self->{curr_subreport} ) {
	$self->{curr_subreport}{date} = $date_epoch;
    } else {
	$self->{report}{date} = $date_epoch;
    }
}

sub handle_timespan {
    my ( $self, $timespan, $start, $end ) = @_;

    if ( $self->{curr_subreport} ) {
	$self->{curr_subreport}{timespan_start} = $start;
	$self->{curr_subreport}{timespan_end} = $end;
    } else {
	$self->{report}{timespan_start} = $start;
	$self->{report}{timespan_end} = $end;
    }
}

sub handle_hostname {
    my ( $self, $hostname ) = @_;

    if ( $self->{curr_subreport} ) {
	$self->{curr_subreport}{hostname} = $hostname;
    } else {
	$self->{report}{hostname} = $hostname;
    }
}

sub description_start {
    my ( $self, %attr )= @_;

    $self->{curr_desc} = { name => $attr{'target-user'}, desc => "" };
    $self->{curr_desc_context} = $self->depth;

    my $o;
    if ( $self->{curr_subreport} ) {
	$o = $self->{curr_subreport};
    } elsif ( $self->{curr_section} ) {
	$o = $self->{curr_section};
    } else {
	$o = $self->{report};
    }
    push @{$o->{descriptions}}, $self->{curr_desc};
}

sub description_end {
    my ( $self )= @_;

    $self->{curr_desc} = undef;
    $self->{curr_desc_context} = undef;
}

sub element_start {
    my ( $self, $name, %attr ) = @_;

    # In description collect everything
    if ( $self->{curr_desc} ) {
	$self->{curr_desc}{desc} .= $self->original_string;
    }

    return 0; # Continue normal processing
}

sub element_end {
    my ( $self, $name ) = @_;

    # In description collect everything
    if ( $self->{curr_desc} && $self->depth > $self->{curr_desc_context} )
    {
	$self->{curr_desc}{desc} .= $self->original_string;
    }

    return 0; # Continue normal processing
}

sub pcdata {
    my ( $self, $str ) = @_;

    # In description collect everything
    if ( $self->{curr_desc} ) {
	$self->{curr_desc}{desc} .= $self->original_string;
    }
    return 0; # Continue normal processing
}

sub ignorable_ws {
    my ( $self, $str ) = @_;

    # In description collect everything
    if ( $self->{curr_desc} ) {
	$self->{curr_desc}{desc} .= $self->original_string;
    }
    return 0; # Continue normal processing
}

sub section_start {
    my ( $self, %attr ) = @_;

    $self->SUPER::section_start( %attr );

    if ( $self->{only_head} ) {
	$self->expat->finish;
	return;
    }

    $self->{curr_section} = bless {
				   subreports	=> [],
				   descriptions => [],
				  }, "Lire::Report::Section";
    push @{$self->{report}{sections}}, $self->{curr_section};
}

sub section_end {
    my ( $self ) = @_;
    $self->SUPER::section_end();

    $self->{curr_section} = undef;
}

sub subreport_start {
    my ( $self,  %attr ) = @_;
    $self->SUPER::subreport_start( %attr );

    my $subreport = bless { 
			   missing => 0,
			   superservice => $attr{superservice} || 
					    $self->{report}{superservice},
			   type		=> $attr{type},
			   entries	=> [],
			   descriptions	=> [],
			   report	=> $self->{report},
			  }, "Lire::Report::Subreport";

    $self->{curr_subreport} = $subreport;
    push @{$self->{curr_section}{subreports}}, $self->{curr_subreport};

    $self->{curr_tables} = [ $self->{curr_subreport}, ];
}

sub subreport_end {
    my ( $self ) = @_;
    $self->SUPER::subreport_end();

    $self->{curr_subreport} = undef;
    pop @{$self->{curr_tables}};
    die "subreport_end(): assertion failed: curr_tables should be empty\n"
      if @{$self->{curr_tables}};
}

sub missing_subreport_start {
    my ( $self, %attr ) = @_;
    $self->SUPER::missing_subreport_start( %attr );

    my $subreport = bless { 
			   # Set defaults based on report
			   superservice => $attr{superservice} ||
					   $self->{report}{superservice},
			   type		=> $attr{type},
			   reason	=> $attr{reason},
			   missing	=> 1,
			   entries	=> [],
			   descriptions	=> [],
			  }, "Lire::Report::Subreport";

    push @{$self->{curr_section}{subreports}}, $subreport;
}

sub table_start {
    my ( $self, %attr ) = @_;
    $self->SUPER::subreport_start( %attr );

    $self->{curr_subreport}{charttype} = $attr{charttype};
    $self->{curr_subreport}{show}      = $attr{show};
}

sub group_start {
    my ( $self, %attr ) = @_;
    $self->SUPER::group_start( %attr );

    $self->{curr_group} = bless {
				 entries => [],
				 show	 => $attr{show},
				}, "Lire::Report::Group";
    push @{$self->{curr_entry}{values}}, $self->{curr_group};

    push @{$self->{curr_tables}}, $self->{curr_group};
}

sub group_end {
    my ( $self ) = @_;
    $self->SUPER::group_end();

    $self->{curr_group} = undef;

    pop @{$self->{curr_tables}};
}

sub entry_start {
    my ( $self, %attr ) = @_;
    $self->SUPER::entry_start( %attr );

    $self->{curr_entry} = bless { 
				 names  => [],
				 values => [],
				}, "Lire::Report::Entry";

    my $table = $self->{curr_tables}[$#{$self->{curr_tables}}];
    push @{$table->{entries}}, $self->{curr_entry};
}

sub entry_end {
    my ( $self ) = @_;
    $self->SUPER::entry_end();

    $self->{curr_entry} = undef;
}

sub handle_name {
    my ( $self, $name ) = @_;

    push @{$self->{curr_entry}{names}}, $name;
}

sub handle_value {
    my ( $self, $value ) = @_;

    push @{$self->{curr_entry}{values}}, $value;
}

sub image_start {
    my ( $self, %attr ) = @_;
    $self->SUPER::image_start( %attr );

    $self->{curr_image} = bless {}, "Lire::Report::Image";
}

sub image_end {
    my ( $self ) = @_;
    $self->SUPER::image_end();

    $self->{curr_subreport}{image} = $self->{curr_image};
    $self->{curr_image} = undef;
}

sub file_start {
    my ( $self, %attr ) = @_;
    $self->SUPER::image_start( %attr );

    $self->{curr_image}{format} = $attr{format};
}

sub handle_file {
    my ( $self, $file ) = @_;
    $self->{curr_image}{file} = $file;
}

# keep perl happy
1;

__END__

=pod

=head1 NAME

Lire::ReportParser::ReportBuilder - Creates Lire::Report objects from XML files

=head1 SYNOPSIS

    use Lire::ReportParser::ReportBuilder;
    my $parser = new Lire::ReportParser::ReportBuilder;
    my $report = $parser->parse( "report.xml" );

=head1 DESCRIPTION

This is a subclass of Lire::ReportParser that creates an object
representation of a Lire report contained in a XML file.

=head1 SEE ALSO

Lire::Report(3pm)

=head1 VERSION

$Id: ReportBuilder.pm,v 1.7 2002/07/28 19:29:17 flacoste Exp $

=head1 COPYRIGHT

Copyright (C) 2001 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 or write to the Free Software 
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.

=head1 AUTHOR

Francis J. Lacoste <flacoste@logreport.org>

=cut
