package Lire::Config::XMLSpecListSpec; use strict; use base qw/Lire::Config::ListSpec/; use Lire::Config::StringSpec; use Lire::Config::ObjectSpec; use Lire::Config::ListSpec; use Lire::Config::ChartSpec; use Lire::ReportSpec; use Lire::FilterSpec; use Lire::Utils qw/check_param/; use Locale::TextDomain 'lire'; use Carp; our $NAME_RE = qr/^([\w_-]+):([\w_.-]+)$/; =pod =head1 NAME Lire::Config::XMLSpecListSpec - List of XML specifications. =head1 DESCRIPTION This Lire::Config::TypeSpec defines a special kind of ListSpec. It overrides the has_component(), get(), component_names() and components() methods so that every XML report specifications or filter specifications are available. The specifications are created dynamically at runtime. =head2 new( 'name' => $name, 'type' => 'filters'|'reports ) Creates a new Lire::Config::XMLSpecListSpec object which will contains a list of report or filter specifications configuration. The type parameter is used to select whether Lire::ReportSpec or Lire::FilterSpec will be creatd. =cut sub new { my $self = shift->SUPER::new( @_ ); my $type = { @_ }->{'type'}; check_param( $type, 'type', qr/^filters|reports$/, "'type' parameter should be either filters or reports" ); $self->{'_type'} = $type; $self->{'_module'} = ( $type eq 'reports' ? 'Lire::ReportSpec' : 'Lire::FilterSpec' ); $self->{'_cache'} = {}; return $self; } =pod =head2 type() Returns the type of specification contained by this object. =cut sub type { return $_[0]{'_type'}; } =pod =head2 has_component( $name ) This spec will return true when $name is of the form I:I and there is an available I specification defined in I. It returns false otherwise. =cut sub has_component { my ( $self, $name ) = @_; check_param( $name, 'name' ); my ( $super, $type ) = $name =~ /$NAME_RE/; return 0 unless defined $super && defined $type; return Lire::DlfSchema->has_superservice( $super ) && $self->{'_module'}->has_spec( $super, $type ); } =pod =head2 component_names() Returns an array containing the configuration name of all available specifications. =cut sub component_names { my $self = $_[0]; my @specs = (); foreach my $super ( Lire::DlfSchema->superservices() ) { foreach my $type ( @{$self->{'_module'}->list_specs( $super )} ) { push @specs, "$super:$type"; } } return @specs; } =pod =head2 get( $name ) Returns an Lire::Config::ObjectSpec specification for the component named $name. The ObjectSpec will instantiate a Lire::ReportSpec or Lire::FilterSpec of the appropriate type. =cut sub get { my ( $self, $name ) = @_; croak "no component named '$name'" unless $self->has_component( $name ); return $self->{'_cache'}{$name} if exists $self->{'_cache'}{$name}; my ( $super, $type ) = $name =~ /$NAME_RE/; my $xml_spec = $self->{'_module'}->load( $super, $type ); my $spec = new Lire::Config::ObjectSpec( 'name' => $name, 'i18n_domain' => "lire-$super", 'class' => $self->{'_module'}, 'summary' => $xml_spec->title(), 'description' => $xml_spec->description(), 'label' => 'id', ); $spec->add( new Lire::Config::StringSpec( 'name' => 'id', 'valid-re' => '^[\w.:-]+$', 'summary' => N__( 'Identifier' ), 'description' => '' . join( "", N__( 'Identifier that uniquely identifies this specification among the report configuration. When two reports are merged, specifications with the same identifier are merged together.' ) ) . "" ) ); my $title = new Lire::Config::StringSpec( 'name' => 'title', 'required' => 0, 'summary' => N__( 'Custom Title' ), 'description' => '' . join( "", N__( 'If this parameter is set, its value will be used instead of the display title specified in the specification. This string will interpolate $name_ref with the parameter\'s value when the report is generated.' ) ) . '' ); $title->default( $title->instance( 'value' => $xml_spec->display_title())); $spec->add( $title ); foreach my $name ( $xml_spec->param_names() ) { $spec->add( $xml_spec->param( $name )->as_type_spec() ); } $self->_set_charts_spec( $xml_spec, $spec ); return $self->{'_cache'}{$name} = $spec; } sub _set_charts_spec { my ( $self, $xml_spec, $spec ) = @_; return unless $xml_spec->isa( 'Lire::ReportSpec' ); my $charts = new Lire::Config::ListSpec( 'name' => 'charts', 'summary' => N__( 'Charts' ), 'description' => '' . join ( "", N__( "Parameters for the charts that should be generated from this subreport's data" ) ) . "" ); $spec->add( $charts ); $charts->add( new Lire::Config::ChartSpec( 'name' => 'chart', 'summary' => N__( 'Chart' ), 'description' => '' . join( "", N__( "Parameters for a chart that should be generated from this subreport's data." ) ) . "" ) ); my $default = $charts->instance(); foreach my $cfg ( @{$xml_spec->chart_configs()} ) { my $default_chart = $cfg->clone(); $default_chart->{'spec'} = $charts->get( 'chart' ); $default->append( $default_chart ); } $charts->default( $default ); return; } =pod =head2 components() Returns an array containing all the Lire::Config::ObjectSpec defining the available specifications. =cut sub components { my $self = $_[0]; my @comps = (); foreach my $name ( $self->component_names() ) { push @comps, $self->get( $name ); } return @comps; } 1; __END__ =pod =head2 SEE ALSO Lire::Config::ReportSectionSpec(3pm), Lire::Config::ReportSpec(3pm), Lire::ReportSpec(3pm), Lire::FilterSpec(3pm). =head1 VERSION $Id: XMLSpecListSpec.pm,v 1.8 2006/07/23 13:16:31 vanbaal Exp $ =head1 AUTHOR Francis J. Lacoste =head1 COPYRIGHT Copyright (C) 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