package Lire::Config::Parser;
use strict;
use base qw/Lire::XMLParser/;
use Lire::Utils qw/ check_object_param /;
use Lire::Config::TypeSpec;
use Lire::Config::Value;
use Carp;
=pod
=head1 NAME
Lire::Config::Parser - Creates a Lire::Config::ConfigFile object from XML
=head1 SYNOPSIS
use Lire::Config;
use Lire::Config::Parser;
my $parser = new Lire::Config::Parser( 'spec' => Lire::Config->config_spec());
my $conf = $parser->parsefile( 'config.xml' );
=head1 DESCRIPTION
Rather straightforward XML parser that follows the configuration
specification to parse an XML file.
=head2 new( 'spec' => $spec )
Creates a parser object which will parse configuration file which
validates against the Lire::Config::ConfigSpec specification $spec.
=cut
sub new {
my $self = shift->SUPER::new();
my %args = @_;
check_object_param( $args{'spec'}, 'spec',
'Lire::Config::ConfigSpec' );
$self->{'spec'} = $args{'spec'};
return $self;
}
sub namespaces {
return { 'http://www.logreport.org/LRCML/' => 'lrcml' };
}
sub elements_spec {
return {
'lrcml:config' => [ 'lrcml:global', 'lrcml:param' ],
'lrcml:global' => [ 'lrcml:param' ],
'lrcml:param' => [ 'PCDATA', 'lrcml:param' ],
};
}
=pod
=head2 load_config_file( $file )
Parses the $file XML file and returns a Lire::Config::ConfigFile
object representing it.
=cut
sub load_config_file {
my ( $self, $file ) = @_;
$self->{'filename'} = $file;
my $conf = eval { $self->parsefile( $file ) };;
croak "error while parsing XML Config $file: $@"
if $@;
return $conf;
}
sub parse_start {
my $self = $_[0];
$self->{'conf'} =
new Lire::Config::ConfigFile( 'spec' => $self->{'spec'},
'filename' => $self->{'filename'},
);
$self->init_stack( 'config_spec' );
$self->init_stack( 'config_value' );
return;
}
sub parse_end {
my $self = $_[0];
return $self->{'conf'};
}
sub param_char {
my ( $self, $text ) = @_;
$self->collect( 'lrcml:param' . $self->depth(), $text );
return;
}
sub current_param_spec {
my ( $self, $name ) = @_;
return $self->stack_peek( 'config_spec' )->get( $name );
}
sub param_start {
my ( $self, $param, $attr ) = @_;
$self->error( "<config> must be the root element" )
if $self->is_stack_empty( 'config_spec' );
my $spec = $self->current_param_spec( $attr->{'name'} );
my $value = $spec->instance( %$attr );
unless ( $self->is_stack_empty( 'config_value' ) ) {
my $parent_value = $self->stack_peek( 'config_value' );
if( $parent_value->isa( "Lire::Config::List" ) ) {
$parent_value->append( $value );
} elsif ( $parent_value->isa("Lire::Config::Dictionary") ) {
$parent_value->set($value);
} else {
$self->error( "unknown parameter container type: $parent_value" );
}
}
$spec = $value->get_properties_spec()
if $value->isa( 'Lire::Config::Plugin' );
# Remove any default since the value is redefined.
$value->clear() if $value->isa( 'Lire::Config::List' );
$self->stack_push( 'config_spec', $spec );
$self->stack_push( 'config_value', $value );
$self->init_collector( 'lrcml:param' . ($self->depth() + 1) );
return;
}
sub param_end {
my $self = $_[0];
$self->stack_pop( 'config_spec' );
my $value = $self->stack_pop( 'config_value' );
if( $value->isa( "Lire::Config::Scalar" ) ) {
local $SIG{'__WARN__'} = sub {};
my $text = $self->get_collector( 'lrcml:param' . ($self->depth() + 1));
$value->set( $text )
unless $text eq '' && $value->get() ne '';
}
return;
}
sub config_start {
my ( $self, $name, $attr ) = @_;
$self->error( "<config> must be the root element" )
unless $self->is_stack_empty( 'config_spec' );
my $global_conf = $self->{'spec'}->instance();
$self->{'conf'}->global( $global_conf );
$self->stack_push( 'config_spec', $self->{'spec'} );
$self->stack_push( 'config_value', $global_conf );
return;
}
sub config_end {
my $self = $_[0];
$self->stack_pop( 'config_spec' );
$self->stack_pop( 'config_value' );
$self->error( "<config> must be the root element" )
unless $self->is_stack_empty( 'config_spec' );
return;
}
# keep perl happy
1;
__END__
=pod
=head1 SEE ALSO
Lire::Config::ConfigFile(3pm), Lire::Config::SpecParser(3pm),
Lire::Config::ConfigSpec(3pm)
=head1 AUTHORS
Wessel Dankers <wsl@logreport.org>
Francis J. Lacoste <flacoste@logreport.org>
=head1 VERSION
$Id: Parser.pm,v 1.49 2006/07/23 13:16:30 vanbaal Exp $
=head1 COPYRIGHT
Copyright (C) 2002, 2004 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.
=cut
syntax highlighted by Code2HTML, v. 0.9.1