package cfgfile2;

# Copyright (C) 1999 Norman Walsh, <ndw@nwalsh.com>
# This program is free software; you can redistribute it and/or modify
# it under the same terms as Perl itself.
#
# WARRANTY
# 
# THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
# PURPOSE.

use strict;
use XML::DOM;

sub new {
    my($type, $cfgfile) = @_;
    my $class = ref($type) || $type;
    my $parser = new XML::DOM::Parser (NoExpand => 1);
    my $self = {};

    if ($cfgfile) {
	$self->{'DOC'} = $parser->parsefile ($cfgfile);
    } else {
	$self->{'DOC'} = $parser->parse("<cfgfile></cfgfile>");
    }
    
    bless $self, $class;
    
    return $self;
}

sub doc {
    my $self = shift;
    return $self->{'DOC'};
}

sub write {
    my $self = shift;
    local *F = shift;
    my $root = $self->doc()->getDocumentElement();
    
    print F "<?xml version='1.0'?>\n";
    $self->writeElement(*F, $root, "");
}

sub writeElement {
    my $self = shift;
    local *F = shift;
    my $element = shift;
    my $indent = shift;
    my $node = $element->getFirstChild();
    my $attrs = $element->getAttributes();
    my ($attr, $count);

    print F $indent, "<", $element->getTagName();
    for ($count = 0; $count < $attrs->getLength(); $count++) {
	$attr = $attrs->item($count);
	print F " ", $attr->getNodeName(), "=\"", $attr->getNodeValue, "\"";
    }

    if (!$node) {
	print F "/>\n";
    } else {
	print F ">\n";
	
	while ($node) {
	    if ($node->getNodeType() == XML::DOM::ELEMENT_NODE) {
		$self->writeElement(*F, $node, "$indent  ");
	    } 
	    $node = $node->getNextSibling();
	}
	print F $indent, "</", $element->getTagName(), ">\n";
    }
}

sub getSection {
    my $self = shift;
    my $name = shift;
    
    return $self->findChild($self->doc()->getDocumentElement(), "section", $name);
}

sub getEntry {
    my $self = shift;
    my $section = shift;
    my $name = shift;
    
    return $self->findChild($section, "entry", $name);
}

sub findChild {
    my $self = shift;
    my $parent = shift;
    my $element = shift;
    my $name = shift;
    my $nodelist = $parent->getElementsByTagName($element);
    my $nodecount = $nodelist->getLength();

    for (my $count = 0; $count < $nodecount; $count++) {
	my $node = $nodelist->item($count);
	if ($node->getTagName() eq $element
	    && $node->getAttribute("name") eq $name) {
	    return $node;
	}
    }

    return undef;
}

sub findChild_walk {
    my $self = shift;
    my $parent = shift;
    my $element = shift;
    my $name = shift;
    my $node = $parent->getFirstChild();

    while ($node) {
	if ($node->getNodeType() == XML::DOM::ELEMENT_NODE
	    && $node->getTagName() eq $element
	    && $node->getAttribute("name") eq $name) {
	    return $node;
	}
	$node = $node->getNextSibling();
    }

    return undef;
}

sub getProfileString {
    my $self = shift;
    my $secname = shift;
    my $varname = shift;
    my $defval = shift;

    if (!$self->doc()) { 
	# This should never happen
	return $defval;
    }

    my $section = $self->getSection($secname);

    return $defval if !$section;

    my $entry = $self->getEntry($section, $varname);

    return $defval if !$entry;

    return $entry->getAttribute("value");
}

sub setProfileString {
    my $self = shift;
    my $secname = shift;
    my $varname = shift;
    my $value = shift;

    if (!$self->doc()) { 
	# This should never happen
	return;
    }

    my $root = $self->doc()->getDocumentElement();

    my $section = $self->getSection($secname);
    if (!$section) {
	$section = $self->doc()->createElement("section");
	$section->setAttribute("name", $secname);
	$root->appendChild($section);
    }

    my $entry = $self->getEntry($section, $varname);
    if (!$entry) {
	$entry = $self->doc()->createElement("entry");
	$entry->setAttribute("name", $varname);
	$section->appendChild($entry);
    }

    $entry->setAttribute("value", $value);
}

1;
