diff options
Diffstat (limited to 'torrus/perllib/Torrus/ConfigBuilder.pm')
-rw-r--r-- | torrus/perllib/Torrus/ConfigBuilder.pm | 529 |
1 files changed, 529 insertions, 0 deletions
diff --git a/torrus/perllib/Torrus/ConfigBuilder.pm b/torrus/perllib/Torrus/ConfigBuilder.pm new file mode 100644 index 000000000..7762c00dc --- /dev/null +++ b/torrus/perllib/Torrus/ConfigBuilder.pm @@ -0,0 +1,529 @@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# This program 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; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: ConfigBuilder.pm,v 1.1 2010-12-27 00:03:40 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +# XML configuration builder + +package Torrus::ConfigBuilder; + +use strict; +use XML::LibXML; +use IO::File; + +use Torrus::Log; + +sub new +{ + my $self = {}; + my $class = shift; + bless $self, $class; + + my $doc = XML::LibXML->createDocument( "1.0", "UTF-8" ); + my $root = $doc->createElement('configuration'); + $doc->setDocumentElement( $root ); + $self->{'doc'} = $doc; + $self->{'docroot'} = $root; + + $root->appendChild($doc->createComment('DO NOT EDIT THIS FILE')); + + my $dsnode = $doc->createElement('datasources'); + $self->{'docroot'}->appendChild( $dsnode ); + $self->{'datasources'} = $dsnode; + + $self->{'required_templates'} = {}; + + $self->{'statistics'} = {}; + + $self->{'registry_overlays'} = []; + + return $self; +} + + +sub setRegistryOverlays +{ + my $self = shift; + + $self->{'registry_overlays'} = []; + push( @{$self->{'registry_overlays'}}, @_ ); +} + + +sub lookupRegistry +{ + my $self = shift; + my $template = shift; + + my $ret = undef; + + foreach my $regOverlay ( @{$self->{'registry_overlays'}} ) + { + if( defined( $regOverlay->{$template} ) ) + { + $ret = $regOverlay->{$template}; + } + } + + if( not defined( $ret ) and + defined( $Torrus::ConfigBuilder::templateRegistry{$template} ) ) + { + $ret = $Torrus::ConfigBuilder::templateRegistry{$template}; + } + + if( not defined( $ret ) ) + { + if( scalar( %Torrus::ConfigBuilder::templateRegistry ) > 0 ) + { + Warn('Template ' . $template . + ' is not listed in ConfigBuilder template registry'); + } + } + + return $ret; +} + + + + +sub addCreatorInfo +{ + my $self = shift; + my $creatorInfo = shift; + + my $creatorNode = $self->{'doc'}->createElement('creator-info'); + $creatorNode->appendText( $creatorInfo ); + $self->{'docroot'}->insertBefore( $creatorNode, $self->{'datasources'} ); +} + + +sub addRequiredFiles +{ + my $self = shift; + + foreach my $file ( $self->requiredFiles() ) + { + $self->addFileInclusion( $file ); + } +} + + +sub addFileInclusion +{ + my $self = shift; + my $file = shift; + + my $node = $self->{'doc'}->createElement('include'); + $node->setAttribute( 'filename', $file ); + $self->{'docroot'}->insertBefore( $node, $self->{'datasources'} ); +} + + +sub startDefinitions +{ + my $self = shift; + + my $node = $self->{'doc'}->createElement('definitions'); + $self->{'docroot'}->insertBefore( $node, $self->{'datasources'} ); + return $node; +} + + +sub addDefinition +{ + my $self = shift; + my $definitionsNode = shift;; + my $name = shift; + my $value = shift; + + my $node = $self->{'doc'}->createElement('def'); + $node->setAttribute( 'name', $name ); + $node->setAttribute( 'value', $value ); + $definitionsNode->appendChild( $node ); +} + + +sub startParamProps +{ + my $self = shift; + + my $node = $self->{'doc'}->createElement('param-properties'); + $self->{'docroot'}->insertBefore( $node, $self->{'datasources'} ); + return $node; +} + + +sub addParamProp +{ + my $self = shift; + my $propsNode = shift;; + my $param = shift; + my $prop = shift; + my $value = shift; + + my $node = $self->{'doc'}->createElement('prop'); + $node->setAttribute( 'param', $param ); + $node->setAttribute( 'prop', $prop ); + $node->setAttribute( 'value', $value ); + $propsNode->appendChild( $node ); +} + + + +sub addSubtree +{ + my $self = shift; + my $parentNode = shift; + my $subtreeName = shift; + my $params = shift; # hash reference with param name-value pairs + my $templates = shift; # array reference with template names + + return $self->addChildElement( 0, $parentNode, $subtreeName, + $params, $templates ); +} + + +sub addLeaf +{ + my $self = shift; + my $parentNode = shift; + my $leafName = shift; + my $params = shift; # hash reference with param name-value pairs + my $templates = shift; # array reference with template names + + return $self->addChildElement( 1, $parentNode, $leafName, + $params, $templates ); +} + + +sub addChildElement +{ + my $self = shift; + my $isLeaf = shift; + my $parentNode = shift; + my $childName = shift; + my $params = shift; + my $templates = shift; + + my $doc = $self->{'doc'}; + + if( not ref( $parentNode ) ) + { + $parentNode = $self->{'datasources'}; + } + + my $childNode = $doc->createElement( $isLeaf ? 'leaf' : 'subtree' ); + $childNode->setAttribute( 'name', $childName ); + $childNode = $parentNode->appendChild( $childNode ); + + if( ref( $templates ) ) + { + foreach my $tmpl ( sort @{$templates} ) + { + $self->addTemplateApplication( $childNode, $tmpl ); + } + } + + $self->addParams( $childNode, $params ); + + return $childNode; +} + + +sub getChildSubtree +{ + my $self = shift; + my $parentNode = shift; + my $childName = shift; + + if( not ref( $parentNode ) ) + { + $parentNode = $self->{'datasources'}; + } + + my @subtrees = + $parentNode->findnodes( 'subtree[@name="' . $childName . '"]' ); + if( not @subtrees ) + { + Error('Cannot find subtree named ' . $childName); + return undef; + } + return $subtrees[0]; +} + + +# Reconstruct the path to the given subtree or leaf +sub getElementPath +{ + my $self = shift; + my $node = shift; + + my $path = ''; + if( $node->nodeName() eq 'subtree' ) + { + $path = '/'; + } + + while( not $node->isSameNode( $self->{'datasources'} ) ) + { + $path = '/' . $node->getAttribute( 'name' ) . $path; + $node = $node->parentNode(); + } + + return $path; +} + + +sub getTopSubtree +{ + my $self = shift; + return $self->{'datasources'}; +} + + +sub addTemplateApplication +{ + my $self = shift; + my $parentNode = shift; + my $template = shift; + + if( not ref( $parentNode ) ) + { + $parentNode = $self->{'datasources'}; + } + + my $found = 0; + + my $reg = $self->lookupRegistry( $template ); + if( defined( $reg ) ) + { + $self->{'required_templates'}{$template} = 1; + my $name = $reg->{'name'}; + if( defined( $name ) ) + { + $template = $name; + } + } + + my $tmplNode = $self->{'doc'}->createElement( 'apply-template' ); + $tmplNode->setAttribute( 'name', $template ); + $parentNode->appendChild( $tmplNode ); +} + + +sub addParams +{ + my $self = shift; + my $parentNode = shift; + my $params = shift; + + if( ref( $params ) ) + { + foreach my $paramName ( sort keys %{$params} ) + { + $self->addParam( $parentNode, $paramName, $params->{$paramName} ); + } + } +} + + +sub addParam +{ + my $self = shift; + my $parentNode = shift; + my $param = shift; + my $value = shift; + + if( not ref( $parentNode ) ) + { + $parentNode = $self->{'datasources'}; + } + + my $paramNode = $self->{'doc'}->createElement( 'param' ); + $paramNode->setAttribute( 'name', $param ); + $paramNode->setAttribute( 'value', $value ); + $parentNode->appendChild( $paramNode ); +} + + +sub addAlias +{ + my $self = shift; + my $parentNode = shift; + my $aliasPath = shift; + + if( not ref( $parentNode ) ) # I hope nobody would need this + { + $parentNode = $self->{'datasources'}; + } + + my $aliasNode = $self->{'doc'}->createElement( 'alias' ); + $aliasNode->appendText( $aliasPath ); + $parentNode->appendChild( $aliasNode ); +} + + +sub setVar +{ + my $self = shift; + my $parentNode = shift; + my $name = shift; + my $value = shift; + + my $setvarNode = $self->{'doc'}->createElement( 'setvar' ); + $setvarNode->setAttribute( 'name', $name ); + $setvarNode->setAttribute( 'value', $value ); + $parentNode->appendChild( $setvarNode ); +} + + + +sub startMonitors +{ + my $self = shift; + + my $node = $self->{'doc'}->createElement('monitors'); + $self->{'docroot'}->appendChild( $node ); + return $node; +} + + +sub addMonitorAction +{ + my $self = shift; + my $monitorsNode = shift;; + my $name = shift; + my $params = shift; + + my $node = $self->{'doc'}->createElement('action'); + $node->setAttribute( 'name', $name ); + $monitorsNode->appendChild( $node ); + + $self->addParams( $node, $params ); +} + + +sub addMonitor +{ + my $self = shift; + my $monitorsNode = shift;; + my $name = shift; + my $params = shift; + + my $node = $self->{'doc'}->createElement('monitor'); + $node->setAttribute( 'name', $name ); + $monitorsNode->appendChild( $node ); + + $self->addParams( $node, $params ); +} + + +sub startTokensets +{ + my $self = shift; + + my $node = $self->{'doc'}->createElement('token-sets'); + $self->{'docroot'}->appendChild( $node ); + return $node; +} + + +sub addTokenset +{ + my $self = shift; + my $tsetsNode = shift;; + my $name = shift; + my $params = shift; + + my $node = $self->{'doc'}->createElement('token-set'); + $node->setAttribute( 'name', $name ); + $tsetsNode->appendChild( $node ); + + $self->addParams( $node, $params ); +} + + +sub addStatistics +{ + my $self = shift; + + foreach my $stats ( sort keys %{$self->{'statistics'}} ) + { + my $node = $self->{'doc'}->createElement('configbuilder-statistics'); + $node->setAttribute( 'category', $stats ); + $node->setAttribute( 'value', $self->{'statistics'}{$stats} ); + $self->{'docroot'}->appendChild( $node ); + } +} + + + +sub requiredFiles +{ + my $self = shift; + + my %files; + foreach my $template ( keys %{$self->{'required_templates'}} ) + { + my $file; + my $reg = $self->lookupRegistry( $template ); + if( defined( $reg ) ) + { + $file = $reg->{'source'}; + } + + if( defined( $file ) ) + { + $files{$file} = 1; + } + else + { + Error('Source file is not defined for template ' . $template . + ' in ConfigBuilder template registry'); + } + } + return( sort keys %files ); +} + + + +sub toFile +{ + my $self = shift; + my $filename = shift; + + my $fh = new IO::File('> ' . $filename); + if( defined( $fh ) ) + { + my $ok = $self->{'doc'}->toFH( $fh, 2 ); + $fh->close(); + return $ok; + } + else + { + return undef; + } +} + +1; + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: |