#! /usr/perl5/bin/perl -w
#
# ident   "@(#)XMLReader.pm 1.1     03/11/27 SMI"
# 
# Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

# 
# Module: ScSnapshot::XMLReader
#

package ScSnapshot::XMLReader;
use strict;
use XML::DOM;

#
# Constructor.
#
sub new {
  my $proto = shift;
  my $class = ref($proto) || $proto;
  my $self  = {};
  $self->{EXIT_CODE} = shift;
  bless ($self, $class);
  return $self;
}

#
# This method exits with bad format eror message
# Arguments:
#   1) Name of the XML image.
#      Canot de undefined
sub badimage {
  my $self = shift;
  my $filename = shift;
  printf STDERR gettext("FATAL INTERNAL ERROR: Invalid image file format: ") 
    . $filename . "\n";
  exit $self->{EXIT_CODE}->getCode("ENOEXEC");
}

#
# Reads an XML file containing an image of the CCR configuration data
# and returns the corresponding Internal Data Representation. Fails 
# on error.
# Arguments:
#   1) Name of the XML image file.
#      Cannot be undefined.
#
sub read {
  my $self = shift;
  my $filename = shift;
  my $parser = new XML::DOM::Parser;
  
  # Check if the file exist
  if(!open(INFILE, "<". $filename)) {
    print STDERR gettext("FATAL ERROR: No such file: ") 
      . "\n\t[" . $filename . "]\n";
    exit $self->{EXIT_CODE}->getCode("ENOENT");
  }
  close(INFILE);
  
  # Get DOM object representing the XML document.
  my $doc = $parser->parsefile($filename);
  
  # Fill in the Internal Data Representation
  my $data;

  # The SunCluster software version
  my $config = $doc->getElementsByTagName("config");
  
  my $item=@{$config}[0];
  $data->{scsoftvers} = $item->getAttribute("software-version");
  $data->{osversion}  = $item->getAttribute("os-version");
  $data->{arch}  = $item->getAttribute("machine-arch");
  
  # For each resource type ...
  foreach my $rtdef ($doc->getElementsByTagName("resource-type")) {
    my $rthash;
    foreach my $node ($rtdef->getChildNodes) {
      # ... read attributes
      if ($node->getNodeName eq "attribute") {
	$rthash->{$node->getAttribute("name")} = 
	  (defined $node->getFirstChild)?
	    $node->getFirstChild->getData:"";
      }
      # ... read parameters
      elsif ($node->getNodeName eq "parameters") {
	foreach my $paramnode ($node->getChildNodes) {
	  # Skip newlines which appear as text nodes in the DOM tree
	  if ($paramnode->getNodeName eq "#text") { 
	    next;
	  }
	  my $paramhash;
	  foreach my $attributenode ($paramnode->getChildNodes) {
	    # Skip newlines which appear as text nodes in the DOM
	    # tree
	    if ($attributenode->getNodeName eq "#text") {
	      next;
	    }
	    $paramhash->{$attributenode->getAttribute("name")} = 
	      (defined $attributenode->getFirstChild)?
		$attributenode->getFirstChild->getData:"";
	  }
	  push(@{$rthash->{params}}, $paramhash);
	}
      }
      # ... read methods
      elsif ($node->getNodeName eq "methods") {
	foreach my $methodnode ($node->getChildNodes) {
	  if ($methodnode->getNodeName eq "#text") {
	    next;
	  }
	  $rthash->{methods}->{$methodnode->getAttribute("type")} = 
	    (defined $methodnode->getFirstChild)?$
	      methodnode->getFirstChild->getData:"";
	}
      } else {
	next;
      }
    }    
    push(@{$data->{rtdefs}}, $rthash);
  }

  # For each resource group ...
  foreach my $rgdef ($doc->getElementsByTagName("resource-group")) {
    my $rghash;
    foreach my $node ($rgdef->getChildNodes) {
      # ... read attributes
      if ($node->getNodeName eq "attribute") {
	$rghash->{$node->getAttribute("name")} = 
	  (defined $node->getFirstChild)?
	    $node->getFirstChild->getData:"";
      }
      # ... read resources
      elsif ($node->getNodeName eq "resources") {
	foreach my $resourcenode ($node->getChildNodes) {
	  # Skip newlines which appear as text nodes in the DOM tree
	  if ($resourcenode->getNodeName eq "#text") {
	    next;
	  }
	  my $resourcehash;
	  # For each resource ...
	  foreach my $subnode ($resourcenode->getChildNodes) {
	    # ... read attributes
	    if ($subnode->getNodeName eq "attribute") {
	      $resourcehash->{$subnode->getAttribute("name")} = 
		(defined $subnode->getFirstChild)?
		  $subnode->getFirstChild->getData:"";
	    }
	    # ... read properties
	    elsif ($subnode->getNodeName eq "properties") {
	      foreach my $propertynode ($subnode->getChildNodes)
		{
		  # Skip newlines which appear as text nodes in
		  # the DOM tree
		  if ($propertynode->getNodeName eq "#text") {
		    next;
		  }
		  my $propertyhash;
		  foreach my $attributenode ($propertynode->getChildNodes) {
		    # Skip newlines which appear as text nodes
		    # in the DOM tree
		    if ($attributenode->getNodeName eq "#text") {
		      next;
		    }
		    $propertyhash->{$attributenode->getAttribute("name")} = 
		      (defined $attributenode->getFirstChild)?
			$attributenode->getFirstChild->getData:"";
		  }
		  push(@{$resourcehash->{properties}}, 
		       $propertyhash);
		}
	    } else {
	      next;
	    }
	  }
	  push(@{$rghash->{resources}}, $resourcehash);
	}
      } else {
	next;
      }
    }    
    push(@{$data->{rgdefs}}, $rghash);
  }
  return $data;
} 

# Return success for module load
1; 
