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( " 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( " 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( " 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 Francis J. Lacoste =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