# MERRenderer.rb
#
# Author: David Joy
#
# These software packages were developed at the National Institute of Standards and Technology
# by employees of the Federal Government in the course of their official duties. Pursuant to 
# title 17 Section 105 of the United States Code this software is not subject to copyright 
# protection and is in the public domain. These software packages are experimental systems.  
# NIST assumes no responsibility whatsoever for its use by other parties, and makes no 
# guarantees, expressed or implied, about its quality, reliability, or any other characteristic. 
# We would appreciate acknowledgement if the software is used.  This software can be 
# redistributed and/or modified freely provided that any derivative works bear some notice that
# they are derived from it, and any modified versions bear some notice that they have been 
# modified.

require 'optparse'
require 'libxml'
include LibXML

options = {}
#Parse options
OptionParser.new do |opts|
  opts.banner = "Usage: MERRenderer.rb [options]"

  opts.on("-m", "--mer MEROUTPUTFILE", "MER Output file to render") do |m|
    options[:mer] = m
  end
  opts.on("-o", "--outfile [OUTFILE]", "Output file for the render") do |o|
    options[:out] = o
  end
  opts.on("-d", "--dtd DTDFILE", "Check MER Output against specified DTD") do |d|
    options[:dtd] = d
  end
end.parse!

#if options bad exit 1
if options[:mer].nil? || options[:dtd].nil?
  abort "Missing required arguments #{options[:mer].nil? ? '-m' : ''} #{options[:dtd].nil? ? '-d' : ''}, run with -h for help.".squeeze(" ")
end
options[:out] += ".txt" if !options[:out].nil? && options[:out] !~ /.txt$/i

#Load MER Output
@mer = XML::Document.file(options[:mer])
if !options[:dtd].nil?
  #Load DTD
  @dtd = XML::Dtd.new(File.read(options[:dtd]))
  puts "Validating.."
  if @mer.validate(@dtd)
    puts "MER output file '#{ options[:mer] }' validated!"
  else
    puts "MER output file '#{ options[:mer] }' did not validate!"
  end
else
  puts "No DTD included, skipping validation.."
end

def rec_render(node, depth)
  tab = "   " #Indentation
  return if node.name =~ /text/i
  puts tab * depth + "#{ node.name.upcase }::#{ node.attributes["id"] }\n"
  node.attributes.each do |a|
    next if a.name =~ /^id$/i
    puts tab * (depth + 1) + "#{ a.name }::#{ a.value }\n"
  end
  node.children.each do |e|
    rec_render(e, depth + 1)
  end
end

#Render
if !options[:out].nil?
  puts "Writing output to file '#{options[:out]}' .."
  $stdout = File.new(options[:out], 'w')
  rec_render(@mer.root, 0)
  $stdout = STDOUT
  puts "Done."
else
  rec_render(@mer.root, 0)
end
