package com.dbxml.xml.dom;

/*
 * dbXML - Native XML Database
 * Copyright (C) 1999-2004  The dbXML Group, L.L.C.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Id: DOMUtils.java,v 1.4 2004/02/12 00:17:58 bradford Exp $
 */

import org.w3c.dom.*;

import com.dbxml.xml.NamespaceMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * DOMUtils provides some common DOM utility methods, typically used by
 * XMLSerializable implementations.
 */

public final class DOMUtils {
   private DOMUtils() {
   }

   public static Element addElement(Element rootElem, String name) {
      Document doc = rootElem.getOwnerDocument();
      Element elem = doc.createElement(name);
      rootElem.appendChild(elem);
      return elem;
   }

   public static void setText(Element elem, String value) {
      Document doc = elem.getOwnerDocument();
      Text text = doc.createTextNode(value);
      elem.appendChild(text);
   }

   public static void iteratorToElements(Element rootElem, String name, Iterator iter) {
      while ( iter.hasNext() ) {
         String val = (String)iter.next();
         Element e = addElement(rootElem, name);
         setText(e, val);
      }
   }

   public static void listToElements(Element rootElem, String name, List l) {
		iteratorToElements(rootElem, name, l.iterator());
   }

   public static void setToElements(Element rootElem, String name, Set s) {
		iteratorToElements(rootElem, name, s.iterator());
   }
	
   public static Element getElement(Element elem, String name) {
      NodeList nl = elem.getElementsByTagName(name);
      if ( nl.getLength() > 0 )
         return (Element)nl.item(0);
      else
         return null;
   }

   public static String getElementText(Element elem, String name) {
      NodeList nl = elem.getElementsByTagName(name);
      if ( nl.getLength() > 0 )
         return getText((Element)nl.item(0));
      else
         return null;
   }

   public static String getText(Element elem) {
      StringBuffer sb = new StringBuffer(64);
      NodeList nl = elem.getChildNodes();
      for ( int i = 0; i < nl.getLength(); i++ ) {
         Node n = nl.item(i);
         switch ( n.getNodeType() ) {
            case Node.TEXT_NODE:
               sb.append(((Text)n).getData());
               break;
            case Node.CDATA_SECTION_NODE:
               sb.append(((CDATASection)n).getData());
               break;
         }
      }
      return sb.toString();
   }

   public static void elementsToList(Element elem, String name, List l) {
      NodeList nl = elem.getElementsByTagName(name);
      for ( int i = 0; i < nl.getLength(); i++ ) {
         Element e = (Element)nl.item(i);
         l.add(getText(e));
      }
   }
	
   public static void elementsToSet(Element elem, String name, Set s) {
      NodeList nl = elem.getElementsByTagName(name);
      for ( int i = 0; i < nl.getLength(); i++ ) {
         Element e = (Element)nl.item(i);
         s.add(getText(e));
      }
   }

	public static void importNamespaces(Element context) {
		Set visited = new TreeSet();
		importNamespaces(context, context, visited);
	}
	
	private static void importNamespaces(Element context, Element elem, Set visited) {
		NamedNodeMap nm = elem.getAttributes();
		for ( int i = 0; i < nm.getLength(); i++ ) {
			Attr attr = (Attr)nm.item(i);
			if ( NamespaceMap.isNamespaceDeclaration(attr) ) {
				String name = attr.getName();
				if ( context == elem )
					visited.add(name);
				else if ( !visited.contains(name) ) {
					visited.add(name);
               context.setAttribute(name, attr.getValue());
				}
			}
		}
		
		Node n = elem.getParentNode();
		if ( n != null && n.getNodeType() == Node.ELEMENT_NODE )
			importNamespaces(context, (Element)n, visited);
	}
}

