/*
 * Copyright 2001-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jboss.axis.utils;

import org.jboss.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.Name;

/**
 * DOM2 utilites
 *
 * @author Thomas Diesler (thomas.diesler@jboss.org)
 */
public final class DOM2Utils
{
   private static Logger log = Logger.getLogger(DOM2Utils.class.getName());

   private static ThreadLocal builderAssociation = new ThreadLocal();

   // Hide the constructor
   private DOM2Utils()
   {
   }

   /**
    * Initialise the the DocumentBuilder
    */
   public static DocumentBuilder getDocumentBuilder()
   {
      DocumentBuilder builder = (DocumentBuilder)builderAssociation.get();
      if (builder == null)
      {
         try
         {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setValidating(false);
            factory.setNamespaceAware(true);
            builder = factory.newDocumentBuilder();
            builderAssociation.set(builder);
         }
         catch (ParserConfigurationException e)
         {
            log.error(e);
         }
      }
      return builder;
   }

   /**
    * Create an Element for a given name
    *
    * @param parent optional parent element
    */
   public static Element createElement(Element parent, String localPart)
   {
      Document doc = getOwnerDocument(parent);
      if (log.isTraceEnabled())
         log.trace("createElement {}" + localPart);
      
      return doc.createElement(localPart);
   }

   /**
    * Create an Element for a given name and prefix
    *
    * @param parent optional parent element
    */
   public static Element createElement(Element parent, String localPart, String prefix)
   {
      Document doc = getOwnerDocument(parent);
      if (log.isTraceEnabled())
         log.trace("createElement {}" + prefix + ":" + localPart);
      
      return doc.createElement(prefix + ":" + localPart);
   }

   /**
    * Create an Element for a given name, prefix and uri
    *
    * @param parent optional parent element
    */
   public static Element createElement(Element parent, String uri, String prefix, String localPart)
   {
      Document doc = getOwnerDocument(parent);
      if (prefix == null || prefix.length() == 0)
      {
         if (log.isTraceEnabled())
            log.trace("createElement {" + uri + "}" + localPart);
         
         return doc.createElementNS(uri, localPart);
      }
      else
      {
         if (log.isTraceEnabled())
            log.trace("createElement {" + uri + "}" + prefix + ":" + localPart);

         return doc.createElementNS(uri, prefix + ":" + localPart);
      }
   }

   /**
    * Create an Element for a given Name object
    *
    * @param parent optional parent element
    */
   public static Element createElement(Element parent, Name name)
   {
      return createElement(parent, name.getURI(), name.getPrefix(), name.getLocalName());
   }

   /**
    * Create a org.w3c.dom.Text node
    */
   public static Text createTextNode(String value)
   {
      DocumentBuilder builder = getDocumentBuilder();
      Document doc = builder.newDocument();
      return doc.createTextNode(value);
   }

   private static Document getOwnerDocument(Node parent)
   {
      DocumentBuilder builder = getDocumentBuilder();
      Document doc = null;
      if (parent != null)
         doc = parent.getOwnerDocument();
      if (doc == null)
         doc = builder.newDocument();
      return doc;
   }
}
