1 # Copyright (C) 2002 Stanislav Sinyagin
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
17 # $Id: ConfigBuilder.pm,v 1.1 2010-12-27 00:03:40 ivan Exp $
18 # Stanislav Sinyagin <ssinyagin@yahoo.com>
20 # XML configuration builder
22 package Torrus::ConfigBuilder;
36 my $doc = XML::LibXML->createDocument( "1.0", "UTF-8" );
37 my $root = $doc->createElement('configuration');
38 $doc->setDocumentElement( $root );
39 $self->{'doc'} = $doc;
40 $self->{'docroot'} = $root;
42 $root->appendChild($doc->createComment('DO NOT EDIT THIS FILE'));
44 my $dsnode = $doc->createElement('datasources');
45 $self->{'docroot'}->appendChild( $dsnode );
46 $self->{'datasources'} = $dsnode;
48 $self->{'required_templates'} = {};
50 $self->{'statistics'} = {};
52 $self->{'registry_overlays'} = [];
58 sub setRegistryOverlays
62 $self->{'registry_overlays'} = [];
63 push( @{$self->{'registry_overlays'}}, @_ );
74 foreach my $regOverlay ( @{$self->{'registry_overlays'}} )
76 if( defined( $regOverlay->{$template} ) )
78 $ret = $regOverlay->{$template};
82 if( not defined( $ret ) and
83 defined( $Torrus::ConfigBuilder::templateRegistry{$template} ) )
85 $ret = $Torrus::ConfigBuilder::templateRegistry{$template};
88 if( not defined( $ret ) )
90 if( scalar( %Torrus::ConfigBuilder::templateRegistry ) > 0 )
92 Warn('Template ' . $template .
93 ' is not listed in ConfigBuilder template registry');
106 my $creatorInfo = shift;
108 my $creatorNode = $self->{'doc'}->createElement('creator-info');
109 $creatorNode->appendText( $creatorInfo );
110 $self->{'docroot'}->insertBefore( $creatorNode, $self->{'datasources'} );
118 foreach my $file ( $self->requiredFiles() )
120 $self->addFileInclusion( $file );
130 my $node = $self->{'doc'}->createElement('include');
131 $node->setAttribute( 'filename', $file );
132 $self->{'docroot'}->insertBefore( $node, $self->{'datasources'} );
140 my $node = $self->{'doc'}->createElement('definitions');
141 $self->{'docroot'}->insertBefore( $node, $self->{'datasources'} );
149 my $definitionsNode = shift;;
153 my $node = $self->{'doc'}->createElement('def');
154 $node->setAttribute( 'name', $name );
155 $node->setAttribute( 'value', $value );
156 $definitionsNode->appendChild( $node );
164 my $node = $self->{'doc'}->createElement('param-properties');
165 $self->{'docroot'}->insertBefore( $node, $self->{'datasources'} );
173 my $propsNode = shift;;
178 my $node = $self->{'doc'}->createElement('prop');
179 $node->setAttribute( 'param', $param );
180 $node->setAttribute( 'prop', $prop );
181 $node->setAttribute( 'value', $value );
182 $propsNode->appendChild( $node );
190 my $parentNode = shift;
191 my $subtreeName = shift;
192 my $params = shift; # hash reference with param name-value pairs
193 my $templates = shift; # array reference with template names
195 return $self->addChildElement( 0, $parentNode, $subtreeName,
196 $params, $templates );
203 my $parentNode = shift;
204 my $leafName = shift;
205 my $params = shift; # hash reference with param name-value pairs
206 my $templates = shift; # array reference with template names
208 return $self->addChildElement( 1, $parentNode, $leafName,
209 $params, $templates );
217 my $parentNode = shift;
218 my $childName = shift;
220 my $templates = shift;
222 my $doc = $self->{'doc'};
224 if( not ref( $parentNode ) )
226 $parentNode = $self->{'datasources'};
229 my $childNode = $doc->createElement( $isLeaf ? 'leaf' : 'subtree' );
230 $childNode->setAttribute( 'name', $childName );
231 $childNode = $parentNode->appendChild( $childNode );
233 if( ref( $templates ) )
235 foreach my $tmpl ( sort @{$templates} )
237 $self->addTemplateApplication( $childNode, $tmpl );
241 $self->addParams( $childNode, $params );
250 my $parentNode = shift;
251 my $childName = shift;
253 if( not ref( $parentNode ) )
255 $parentNode = $self->{'datasources'};
259 $parentNode->findnodes( 'subtree[@name="' . $childName . '"]' );
262 Error('Cannot find subtree named ' . $childName);
269 # Reconstruct the path to the given subtree or leaf
276 if( $node->nodeName() eq 'subtree' )
281 while( not $node->isSameNode( $self->{'datasources'} ) )
283 $path = '/' . $node->getAttribute( 'name' ) . $path;
284 $node = $node->parentNode();
294 return $self->{'datasources'};
298 sub addTemplateApplication
301 my $parentNode = shift;
302 my $template = shift;
304 if( not ref( $parentNode ) )
306 $parentNode = $self->{'datasources'};
311 my $reg = $self->lookupRegistry( $template );
312 if( defined( $reg ) )
314 $self->{'required_templates'}{$template} = 1;
315 my $name = $reg->{'name'};
316 if( defined( $name ) )
322 my $tmplNode = $self->{'doc'}->createElement( 'apply-template' );
323 $tmplNode->setAttribute( 'name', $template );
324 $parentNode->appendChild( $tmplNode );
331 my $parentNode = shift;
336 foreach my $paramName ( sort keys %{$params} )
338 $self->addParam( $parentNode, $paramName, $params->{$paramName} );
347 my $parentNode = shift;
351 if( not ref( $parentNode ) )
353 $parentNode = $self->{'datasources'};
356 my $paramNode = $self->{'doc'}->createElement( 'param' );
357 $paramNode->setAttribute( 'name', $param );
358 $paramNode->setAttribute( 'value', $value );
359 $parentNode->appendChild( $paramNode );
366 my $parentNode = shift;
367 my $aliasPath = shift;
369 if( not ref( $parentNode ) ) # I hope nobody would need this
371 $parentNode = $self->{'datasources'};
374 my $aliasNode = $self->{'doc'}->createElement( 'alias' );
375 $aliasNode->appendText( $aliasPath );
376 $parentNode->appendChild( $aliasNode );
383 my $parentNode = shift;
387 my $setvarNode = $self->{'doc'}->createElement( 'setvar' );
388 $setvarNode->setAttribute( 'name', $name );
389 $setvarNode->setAttribute( 'value', $value );
390 $parentNode->appendChild( $setvarNode );
399 my $node = $self->{'doc'}->createElement('monitors');
400 $self->{'docroot'}->appendChild( $node );
408 my $monitorsNode = shift;;
412 my $node = $self->{'doc'}->createElement('action');
413 $node->setAttribute( 'name', $name );
414 $monitorsNode->appendChild( $node );
416 $self->addParams( $node, $params );
423 my $monitorsNode = shift;;
427 my $node = $self->{'doc'}->createElement('monitor');
428 $node->setAttribute( 'name', $name );
429 $monitorsNode->appendChild( $node );
431 $self->addParams( $node, $params );
439 my $node = $self->{'doc'}->createElement('token-sets');
440 $self->{'docroot'}->appendChild( $node );
448 my $tsetsNode = shift;;
452 my $node = $self->{'doc'}->createElement('token-set');
453 $node->setAttribute( 'name', $name );
454 $tsetsNode->appendChild( $node );
456 $self->addParams( $node, $params );
464 foreach my $stats ( sort keys %{$self->{'statistics'}} )
466 my $node = $self->{'doc'}->createElement('configbuilder-statistics');
467 $node->setAttribute( 'category', $stats );
468 $node->setAttribute( 'value', $self->{'statistics'}{$stats} );
469 $self->{'docroot'}->appendChild( $node );
480 foreach my $template ( keys %{$self->{'required_templates'}} )
483 my $reg = $self->lookupRegistry( $template );
484 if( defined( $reg ) )
486 $file = $reg->{'source'};
489 if( defined( $file ) )
495 Error('Source file is not defined for template ' . $template .
496 ' in ConfigBuilder template registry');
499 return( sort keys %files );
507 my $filename = shift;
509 my $fh = new IO::File('> ' . $filename);
512 my $ok = $self->{'doc'}->toFH( $fh, 2 );
527 # indent-tabs-mode: nil
528 # perl-indent-level: 4