package basics.utl;

import java.util.Iterator;
import java.util.Vector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import basics.testing.Test;

/**
 * @author MNovotny, DSchulz, ks 
 * Convenience class for accessing value in an xml structure.
 * Converting string values into simple types. In case a value can't be converted, 
 * a default value is returned. 
 * Note: if value and expected type don't match, no exception will warn the client.
 */
public class XmlDomUtl
{
private XmlDomUtl()
{
}

public static Document createDocument()
{
   try
   {
      DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
      DocumentBuilder docBuilder;
      docBuilder = dbfac.newDocumentBuilder();
      return docBuilder.newDocument();
   }
   catch(ParserConfigurationException e)
   {
   }
   return null;
}

/**
 * @param element
 */
public static String getElementValue(Element element)
{
   String result = null;
   Node textChild = null;
   if(element != null)
   {
      textChild = element.getFirstChild();
      if(textChild != null)
      {
         if(textChild.getNodeType() == Element.TEXT_NODE)
         {
            result = textChild.getNodeValue();
         }
         else
            if(textChild.getNodeType() == Element.CDATA_SECTION_NODE)
            {
               result = ((CDATASection)textChild).getData();
            }
      }
   }
   return result;
}

/**
 * @param element
 * @param defaultValue
 */
public static int getElementValue(Element element, int defaultValue)
{
   String value = null;
   int result = defaultValue;
   value = getElementValue(element);
   if(value != null)
   {
      try
      {
         result = Integer.parseInt(value);
      }
      catch(NumberFormatException e)
      {
         result = defaultValue;
      }
   }
   return result;
}

/**
 * @param element
 * @param defaultValue
 */
public static double getElementValue(Element element, double defaultValue)
{
   String value = null;
   double result = defaultValue;
   value = getElementValue(element);
   if(value != null)
   {
      try
      {
         result = Double.parseDouble(value);
      }
      catch(NumberFormatException e)
      {
         result = defaultValue;
      }
   }
   return result;
}

/**
 * @param element
 * @param defaultValue
 */
public static String getElementValue(Element element, String defaultValue)
{
   String result = defaultValue;
   String value = null;
   value = getElementValue(element);
   if(value != null)
   {
      result = value;
   }
   return result;
}

// /**
// * @param element
// * @param tagName
// * @param defaultValue
// * @return
// */
// public Date getElementValue(Element element, Date defaultValue)
// {
// String value = null;
// Date result = defaultValue;
//
// DateHelper dateHelper = new DateHelper();
//
// value = getElementValue(element);
//
// logger.debug("Lese Date-Wert: " + value + " in Element");
//		
// if (value != null)
// {
// result = dateHelper.stringToDate(value, DateHelper.DEFAULT_FORMAT);
//
// if (result == null)
// {
// result = defaultValue;
//
// logger.warn(
// "Wert nicht als Date erkannt: " + value);
// }
// }
// return result;
// }
/**
 * @param element
 * @param defaultValue
 */
public static String getElementValue(Element element, String tagName, String defaultValue)
{
   String result = defaultValue;
   String value = null;
   Node textChild = null;
   if(element != null && tagName != null)
   {
      element = getFirstElementByName(element, tagName);
      if(element != null)
      {
         textChild = element.getFirstChild();
         if(textChild != null)
         {
            if(textChild.getNodeType() == Element.TEXT_NODE)
            {
               value = textChild.getNodeValue();
            }
            else
               if(textChild.getNodeType() == Element.CDATA_SECTION_NODE)
               {
                  value = ((CDATASection)textChild).getData();
               }
         }
      }
   }
   if(value != null)
   {
      result = value;
   }
   return result;
}

/**
 * Liest erstes Kind-Element, das
 * @param tagname entspricht, einem gegebenen XML-Element.
 */
public static Element getFirstElementByName(Element root, String tagname)
{
   Element result = null;
   if(root != null)
   {
      NodeList elements = root.getElementsByTagName(tagname);
      if((elements != null) && (elements.getLength() != 0))
      {
         Node candidate = elements.item(0);
         if(candidate instanceof Element)
         {
            result = (Element)candidate;
         }
      }
   }
   return result;
}

/**
 * @param element
 * @param tagName
 * @param defaultValue
 */
public static boolean getElementValue(Element element, String tagName, boolean defaultValue)
{
   String value = null;
   boolean result = defaultValue;
   value = getElementValue(element, tagName, "");
   if(value != null)
   {
      if(value.equalsIgnoreCase("true"))
      {
         result = true;
      }
      else
         if(value.equalsIgnoreCase("false"))
         {
            result = false;
         }
   }
   return result;
}

/**
 * @param element
 * @param tagName
 * @param defaultValue
 */
public static long getElementValue(Element element, String tagName, long defaultValue)
{
   String value = null;
   long result = defaultValue;
   value = getElementValue(element, tagName, "");
   if(value != null && value.length() != 0)
   {
      try
      {
         result = Long.parseLong(value);
      }
      catch(NumberFormatException e)
      {
         result = defaultValue;
      }
   }
   return result;
}

/**
 * @param element
 * @param tagName
 * @param defaultValue
 */
public static int getElementValue(Element element, String tagName, int defaultValue)
{
   String value = null;
   int result = defaultValue;
   value = getElementValue(element, tagName, "");
   if(value != null && value.length() != 0)
   {
      try
      {
         result = Integer.parseInt(value);
      }
      catch(NumberFormatException e)
      {
         result = defaultValue;
      }
   }
   return result;
}

/**
 * @param element
 * @param tagName
 * @param defaultValue
 */
public static double getElementValue(Element element, String tagName, double defaultValue)
{
   String value = null;
   double result = defaultValue;
   value = getElementValue(element, tagName, "");
   if(value != null && value.length() != 0)
   {
      try
      {
         result = Double.parseDouble(value);
      }
      catch(NumberFormatException e)
      {
         result = defaultValue;
      }
   }
   return result;
}

// /**
// * @param element
// * @param tagName
// * @param defaultValue
// */
// public Date getElementValue(Element element, String tagName, Date
// defaultValue)
// {
// String value = null;
// Date result = defaultValue;
//
// DateHelper dateHelper = new DateHelper();
//
// value = getElementValue(element, tagName, "");
//
// logger.debug("Lese Date-Wert: " + value + " in Element: " + tagName);
//		
// if (value != null && value.length() != 0)
// {
// result = dateHelper.stringToDate(value, DateHelper.DEFAULT_FORMAT);
//
// if (result == null)
// {
// result = defaultValue;
//
// logger.warn(
// "Wert in <" + tagName + "> nicht als Date erkannt: " + value);
// }
// }
// return result;
// }
/**
 * @param root
 * @param tagname
 */
public static Iterator<Element> getElementsByName(Element root, String tagname)
{
   NodeList childsNodes = root.getChildNodes();
   Vector<Element> result = new Vector<Element>();
   for(int i = 0; i < childsNodes.getLength(); i++)
   {
      Node currentNode = childsNodes.item(i);
      if(currentNode.getNodeType() == Node.ELEMENT_NODE
         && ((Element)currentNode).getTagName().equals(tagname))
      {
         result.add((Element)currentNode);
      }
   }
   return result.iterator();
}

public static String getAttribute(Element element, String attribute, String defaultValue)
{
   String s = element.getAttribute(attribute);
   return (s == null) ? defaultValue : s;
}

public static boolean getAttribute(Element element, String attribute, boolean defaultValue)
{
   String s = element.getAttribute(attribute);
   return (s == null) ? defaultValue : SUtl.toBoolean(s, defaultValue);
}

public static int getAttribute(Element element, String attribute, int defaultValue)
{
   String s = element.getAttribute(attribute);
   return (s == null) ? defaultValue : SUtl.toInt(s, defaultValue);
}

public static long getAttribute(Element element, String attribute, long defaultValue)
{
   String s = element.getAttribute(attribute);
   return (s == null) ? defaultValue : SUtl.toLong(s, defaultValue);
}

public static double getAttribute(Element element, String attribute, double defaultValue)
{
   String s = element.getAttribute(attribute);
   return (s == null) ? defaultValue : SUtl.toDouble(s, defaultValue);
}

public static void unittest()
{
   Document doc = createDocument();
   Test.assertNotNull(doc, "xml doc is null");
   Element root = doc.createElement("root");
   doc.appendChild(root);
   Element child = doc.createElement("child");
   child.setAttribute("name", "true");
   root.appendChild(child);
   String testvalue = "This is a text entry.";
   Text text = doc.createTextNode(testvalue);
   child.appendChild(text);
   Test.assertTrue(getAttribute(child, "name", false), "attribute name was not true");
   Test.assertNotNull(getElementValue(root, "child", null), "child with text not found");
   Test.assertEqualsTrue(getElementValue(root, "child", ""), testvalue,
      "child with text content incorrect");
}
}
