package Catalog::RF;
use Catalog::XML;
use Catalog;
use strict;
#
# Resource File (RF) utilities
# Author: Christian Cadieux
# Transform back and forth between storade resource files and XML documents.


#######################################
# RESOURCE FILE PARSING
# Format:
# [section1]
# name1=value1
# name2=value2
# ..
# $report = XML->parseResourceFile("3310_policies", 
#               {
#               root => "policies", 
#            section_name => "policy",  # [policy01]
#               };
#######################################
use vars qw($ERR);
sub err {
  my($class, $err) = @_;
  $ERR = $err;
  print "$err \n";
  return;
}


sub file_name {
  my($class, $file) = @_;
  my @L = split(/\//, $file);
  return $L[$#L];
}

sub info {
  return { ROOT => "policies",
          hash  => { property => "name" },
          array => { policy => "name" },
          section_name => "section",
 };
}


sub fileName {
  my($node) = @_;
  foreach my $el (keys %$node) {
     if (exists $node->{$el}{_ATT}) {
        return $node->{$el}{_ATT}{file};
     }
  }
}

sub parseFile {
  my($class, $file, $arg) = @_;

  my $D = System->get_home();
  if (open(O, "$D/$file")) {
     my @l = <O>; close(O);
     return  $class->parse(\@l, $class->file_name($file));
  } else {
     $class->err("opening $file: $! \n");
     return undef;
  }
}


sub parse {
  my($class, $array, $file_name) = @_;
  my $section;
  my $arg = $class->info();
  my $section_name = $arg->{section_name};
  my $R = {};
  my $out;
  $out .= "<$arg->{ROOT} file=\"$file_name\" revision=\"\$" . "Revision:\$\">\n";
  foreach my $l (@$array) {
    chomp($l);
    next if ($l =~ /^\s*$/);
    if (substr($l,0,1) eq "#") {
         $out .= "<!-- $l -->\n";
         next;
    }
    if ($l =~ /^\[(.+)\]/) {
        if ($section) {
           $out .= "   </$section_name>\n";
        }
        $section = $1;
        $out .= "  <$section_name name=\"$section\">\n";
    } else {
        my($name, $val) = split(/\s*\=\s*/, $l, 2);
        if ($class->can("parse_$name")) {
          my $f = "parse_$name";
          $out .= "   " . $class->$f($name, $val);
        } else {
          $out .= "   <property name=\"$name\">$val</property>\n";
        }
    }
  }
  $out .= "</$section_name>\n" if ($section);
  $out .= "</$arg->{ROOT}>\n";
  my $report =  Catalog::XML->parse($out, $class->info());
  bless($report, "Catalog::RF");
  return $report;
}

sub toText {
  my($class, $report, $arg) = @_;
  if (ref($class)) {
    $arg = $report; $report = $class;
  }
  my ($out, $x);
  my $root =  $report->{_ARG}{ROOT} || $arg->{ROOT};
  
  my $r = $report->{$root};

  foreach my $el (keys %$r) {
      my $v = $r->{$el};
      next if ($el eq "_ATT");
      if (ref($v) eq "HASH") {
         foreach my $el (sort keys %$v) {
             next if (substr($el,0,1) eq "_");
             $out .= $report->resourceElement($v->{$el});
         }
      } elsif (ref($v) eq "ARRAY") {
         for ($x=0; $x <= $#$v; $x++) {
            $out .= $report->resourceElement($v->[$x]);
         }
      }
  }
  return $out;
}

sub resourceElement {
  my($class, $el) = @_;
  my $out;
  $out = "[" . $el->{_ATT}{name} . "]\n";
  my $els = $el->{property};
  foreach my $e (sort keys %$els) {
     next if (substr($e,0,1) eq "_");
     $out .= "$els->{$e}{_ATT}{name}=$els->{$e}{_VAL}\n";
  }
  $out .= "\n";
  return $out;
}

sub toXML {
  my( $node, $arg) = @_;

  my ($s) = $node->_toXML($node->{_ARG}{ROOT}, $node, 0, $arg || $node->{_ARG});
  return "$s\n";
}


sub _toXML {
  my($class, $el, $n1, $level, $arg, $skip) = @_;
  my $out;

  if ($n1 =~ /HASH/) {
      return ($n1->{_VAL}, 1) if ($n1->{_VAL});
      foreach my $k (sort keys %$n1) {
          next if (substr($k,0,1) eq "_");
          if ($arg->{hash}{$k}) {
            my $v1 = $n1->{$k};
            foreach my $k2 (sort keys %$v1) {
               next if (substr($k2,0,1) eq "_");
               my ($s1, $sameline) = $class->_toXML($k2, $v1->{$k2}, $level+1, $arg);
               $out .= $class->tag($k, $v1->{$k2}, $level, $s1, $sameline);
            }
          } elsif ($arg->{array}{$k}) {
            my ($s1, $sameline) = $class->_toXML($k, $n1->{$k}, $level+1, $arg);
            $out .= $s1;
          } else {
            my ($s1, $sameline) = $class->_toXML($k, $n1->{$k}, $level+1, $arg);
            $out .= $class->tag($k, $n1->{$k}, $level, $s1, $sameline);
          }
      }

  } elsif (ref($n1) eq "ARRAY") {
      my($x);
      for ($x=0; $x <= $#$n1; $x++) {
          my ($s1, $sameline) = $class->_toXML($el, $n1->[$x], $level+1, $arg);
          $out .= $class->tag($el, $n1->[$x], $level, $s1, $sameline);
      }
  }

  return ($out, 0);
}
sub tag {
  my($class, $el, $node, $level, $content, $sameline) = @_;
  my $s = "\n" . ("  " x $level) . "<$el";
  if (exists  $node->{_ATT}) {
     my $attrs = $node->{_ATT};
     foreach my $at (sort keys %$attrs) {
       next if (substr($at,0,1) eq "_");
       $s .= " $at=\"$attrs->{$at}\"";
     }
  }
  if (!$content) {
    $s .= " />";
  } else {
    $s .= ">";
    $s .= $content;
    if (!$sameline) {
       $s .= "\n" . ("  " x $level) ;
    }
    $s .= "</$el>";
  }
  return $s;
}

1;
