/*
** Module   : XmlHelper.java
** Abstract : XML processing utilities 
**
** Copyright (c) 2009, Golden Code Development Corporation.
**
** -#- -I- --Date-- -----------------------Description------------------------
** 001 GES 20090319 XML processing utilities.
*/

/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.goldencode.harness;

import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import com.goldencode.util.*;

/**
 * XML processing utilities.
 */
public class XmlHelper
{
   /**
    * Load the document stored in the specified XML file.
    *
    * @param    filename
    *           Path and filename of the XML file.
    * @param    rc
    *           Object in which to store the details of any failure.
    *
    * @return   The XML document or <code>null</code> if any failure has
    *           occurred.
    */
   public static Document loadDocument(String filename, FailureNotification rc) 
   {
      Document dom = null;
      
      if (filename == null)
      {
         rc.setResult(ExitCode.MISSING_FILENAME);
         return null;
      }
      
      File source = new File(filename);
      
      if (!source.exists() || !source.isFile())
      {
         rc.setResult(ExitCode.INVALID_FILENAME);
         rc.setDetails(filename);
         return null;
      }
      
      BufferedInputStream bis = null;
      
      try
      {
         bis = new BufferedInputStream(new FileInputStream(source));
         
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         factory.setValidating(false);
         factory.setNamespaceAware(false);
         
         DocumentBuilder builder = factory.newDocumentBuilder();
         dom = builder.parse(bis);
      }
      
      catch (Exception exc)
      {
         rc.setResult(ExitCode.INVALID_CONTENT);
         rc.setDetails(LogHelper.dumpThrowable(exc));
      }
      
      finally
      {
         // clean up the stream
         if (bis != null)
         {
            try
            {
               bis.close();
            }
            
            catch (IOException ioe)
            {
               // ignore
            }
         }
      }
      
      return dom;
   }
   
   /**
    * Get the specified attribute and convert it to an integer.  If it is
    * not present, return the given default value.
    *
    * @param    elem
    *           The node to search for the attribute.
    * @param    name
    *           The attribute name for which to search.
    * @param    defVal
    *           The default value to return if no attribute of that name is
    *           found OR if there is any error.
    *
    * @return   The parsed value or the given default value.
    */
   public static int getAttributeInt(Element elem, String name, int defVal)
   {
      int num = defVal;
      
      String numTxt = elem.getAttribute(name);
      
      if (numTxt != null && numTxt.length() > 0)
      {
         try
         {
            num = Integer.parseInt(numTxt);
         }
         
         catch (NumberFormatException nfe)
         {
            // ignore and return the default
         }
      }
      
      return num;
   }
   
   /**
    * Get the specified attribute and convert it to a 64-bit integer.  If it is
    * not present, return the given default value.
    *
    * @param    elem
    *           The node to search for the attribute.
    * @param    name
    *           The attribute name for which to search.
    * @param    defVal
    *           The default value to return if no attribute of that name is
    *           found OR if there is any error.
    *
    * @return   The parsed value or the given default value.
    */
   public static long getAttributeLong(Element elem, String name, long defVal)
   {
      long num = defVal;
      
      String numTxt = elem.getAttribute(name);
      
      if (numTxt != null && numTxt.length() > 0)
      {
         try
         {
            num = Long.parseLong(numTxt);
         }
         
         catch (NumberFormatException nfe)
         {
            // ignore and return the default
         }
      }
      
      return num;
   }
   
   /**
    * Get the specified attribute and convert it to a boolean value.  If it is
    * not present, return the given default value.
    *
    * @param    elem
    *           The node to search for the attribute.
    * @param    name
    *           The attribute name for which to search.
    * @param    defVal
    *           The default value to return if no attribute of that name is
    *           found OR if there is any error.
    *
    * @return   The parsed value or the given default value.
    */
   public static boolean getAttributeBoolean(Element elem,
                                             String  name,
                                             boolean defVal)
   {
      boolean result = defVal;
      
      String value = elem.getAttribute(name);
      
      if (value != null && value.length() > 0)
      {
         if ("true".equalsIgnoreCase(value))
         {
            result = true;
         }
      }
      
      return result;
   }
}
