/*******************************************************************************
 * Copyright (c) 2003, 2011 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - Initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.server.tomcat.core.internal.xml;

import java.util.LinkedHashMap;
import java.util.Map;

import org.w3c.dom.*;
/**
 * An XML element.
 */
public class XMLElement {
	private Element xmlElement;
	protected Factory factory;

	public XMLElement() {
		// do nothing
	}
	
	public Element getElementNode() {
		return xmlElement;
	}

	public Attr addAttribute(String s, String s1) {
		Attr attr = factory.createAttribute(s, xmlElement);
		attr.setValue(s1);
		return attr;
	}

	public XMLElement createElement(int index, String s) {
		return factory.createElement(index, s, xmlElement);
	}

	public XMLElement createElement(String s) {
		return factory.createElement(s, xmlElement);
	}

	public XMLElement findElement(String s) {
		NodeList nodelist = xmlElement.getElementsByTagName(s);
		int i = nodelist == null ? 0 : nodelist.getLength();
		for (int j = 0; j < i; j++) {
			Node node = nodelist.item(j);
			String s1 = node.getNodeName().trim();
			if (s1.equals(s))
				return factory.newInstance((Element) node);
		}
	
		return createElement(s);
	}

	public XMLElement findElement(String s, int i) {
		NodeList nodelist = xmlElement.getElementsByTagName(s);
		int j = nodelist == null ? 0 : nodelist.getLength();
		for (int k = 0; k < j; k++) {
			Node node = nodelist.item(k);
			String s1 = node.getNodeName().trim();
			if (s1.equals(s) && k == i)
				return factory.newInstance((Element) node);
		}
	
		return createElement(s);
	}

	public String getAttributeValue(String s) {
		Attr attr = xmlElement.getAttributeNode(s);
		if (attr != null)
			return attr.getValue();
		
		return null;
	}
	
	public Map getAttributes() {
		Map<String, String> attributes = new LinkedHashMap<String, String>();
		NamedNodeMap attrs = xmlElement.getAttributes();
		if (null != attrs) {
			for (int i = 0; i < attrs.getLength(); i++) {
				Node attr = attrs.item(i);
				String name = attr.getNodeName();
				String value = attr.getNodeValue();
				attributes.put(name, value);
			}
		}
		return attributes;
	}
	
	public String getElementName() {
		return xmlElement.getNodeName();
	}
	
	public String getElementValue() {
		return getElementValue(xmlElement);
	}
	
	protected static String getElementValue(Element element) {
		String s = element.getNodeValue();
		if (s != null)
			return s;
		NodeList nodelist = element.getChildNodes();
		for (int i = 0; i < nodelist.getLength(); i++)
			if (nodelist.item(i) instanceof Text)
				return ((Text) nodelist.item(i)).getData();
	
		return null;
	}
	
	public Element getSubElement(String s) {
		NodeList nodelist = xmlElement.getElementsByTagName(s);
		int i = nodelist == null ? 0 : nodelist.getLength();
		for (int j = 0; j < i; j++) {
			Node node = nodelist.item(j);
			String s1 = node.getNodeName().trim();
			if (s1.equals(s))
				return (Element) node;
		}
	
		return null;
	}

	public String getSubElementValue(String s) {
		Element element = getSubElement(s);
		if (element == null)
			return null;
	
		String value = getElementValue(element);
		if (value == null)
			return null;
		
		return value.trim();
	}

	public boolean removeAttribute(String s) {
		try {
			xmlElement.removeAttribute(s);
			return true;
		} catch (Exception ex) {
			return false;
		}
	}

	public boolean removeElement(String s, int i) {
		NodeList nodelist = xmlElement.getElementsByTagName(s);
		int j = nodelist == null ? 0 : nodelist.getLength();
		for (int k = 0; k < j; k++) {
			Node node = nodelist.item(k);
			String s1 = node.getNodeName().trim();
			if (s1.equals(s) && k == i) {
				xmlElement.removeChild(node);
				return true;
			}
		}
	
		return false;
	}

	public void setAttributeValue(String s, String s1) {
		Attr attr = xmlElement.getAttributeNode(s);
		if (attr == null)
			attr = addAttribute(s, s1);
		else
			attr.setValue(s1);
	}

	void setElement(Element element) {
		xmlElement = element;
	}

	protected static void setElementValue(Element element, String value) {
		String s = element.getNodeValue();
		if (s != null) {
			element.setNodeValue(value);
			return;
		}
		NodeList nodelist = element.getChildNodes();
		for (int i = 0; i < nodelist.getLength(); i++)
			if (nodelist.item(i) instanceof Text) {
				Text text = (Text) nodelist.item(i);
				text.setData(value);
				return;
			}
	
		return;
	}

	void setFactory(Factory factory1) {
		factory = factory1;
	}

	public void setSubElementValue(String s, String value) {
		Element element = getSubElement(s);
		if (element == null) {
			element = factory.document.createElement(s);
			element.appendChild(factory.document.createTextNode("temp"));
			xmlElement.appendChild(element);
		}
		setElementValue(element, value);
	}

	public int sizeOfElement(String s) {
		NodeList nodelist = xmlElement.getElementsByTagName(s);
		int i = nodelist == null ? 0 : nodelist.getLength();
		return i;
	}

	public void updateElementValue(String s) {
		try {
			xmlElement.setNodeValue(s);
		} catch (DOMException ex) {
			NodeList nodelist = xmlElement.getChildNodes();
			int i = nodelist == null ? 0 : nodelist.getLength();
			if (i > 0) {
				for (int j = 0; j < i; j++)
					if (nodelist.item(j) instanceof Text) {
						((Text) nodelist.item(j)).setData(s);
						return;
					}
			} else {
				xmlElement.appendChild(factory.document.createTextNode(s));
			}
		}
	}
	
	public boolean hasChildNodes() {
		return xmlElement.hasChildNodes();
	}
	
	public void removeChildren()
	{
		while (xmlElement.hasChildNodes()) {
			xmlElement.removeChild(xmlElement.getFirstChild());
		}
	}
	
	public void copyChildrenTo(XMLElement destination) {
		NodeList nodelist = xmlElement.getChildNodes();
		int len = nodelist == null ? 0 : nodelist.getLength();
		for (int i = 0; i < len; i++) {
			Node node = nodelist.item(i);
			destination.importNode(node, true);
		}
	}
	
	public void importNode(Node node, boolean deep) {
		xmlElement.appendChild(xmlElement.getOwnerDocument().importNode(node, deep));
	}

	/**
	 * This method tries to compare two XMLElements for equivalence. Due to
	 * the lack of normalization, they aren't compared for equality. Elements
	 * are required to have the same attributes or the same node value
	 * if attributes aren't present. Attributes and node value are assumed
	 * to be mutually exclusive for Tomcat configuration XML files. The
	 * same non-text child nodes are required to be present in an element
	 * and appear in the same order. If a node type other than element or
	 * comment is encountered, this method punts and returns false.
	 * 
	 * @param obj XMLElement to compare
	 * @return true if the elements are equivalent
	 */
	public boolean isEquivalent(XMLElement obj) {
		if (obj != null) {
			try {
				return elementsAreEquivalent(xmlElement, obj.getElementNode());
			}
			catch (Exception e) {
				// Catch and ignore just to be safe
			}
		}
		return false;
	}

	/**
	 * Same as isEquivalent() but doesn't ignore exceptions for test purposes.
	 * This avoids hiding an expected mismatch behind an unexpected exception.
	 * 
	 * @param obj XMLElement to compare
	 * @return true if the elements are equivalent
	 */
	public boolean isEquivalentTest(XMLElement obj) {
		if (obj != null) {
			return elementsAreEquivalent(xmlElement, obj.getElementNode());
		}
		return false;
	}
	
	private static boolean elementsAreEquivalent(Element element, Element otherElement) {
		if (element == otherElement)
			return true;
		
		if (!element.getNodeName().equals(otherElement.getNodeName()))
			return false;
		
		if (element.hasChildNodes()) {
			if (otherElement.hasChildNodes() && attributesAreEqual(element, otherElement)) {
				// Compare child nodes
				NodeList nodelist = element.getChildNodes();
				NodeList otherNodelist = otherElement.getChildNodes();
				if (nodelist.getLength() == otherNodelist.getLength()) {
					Node node = nextNonTextNode(element.getFirstChild());
					Node otherNode = nextNonTextNode(otherElement.getFirstChild());
					while (node != null) {
						if (otherNode == null)
							return false;
						short nextNodeType = node.getNodeType();
						if (nextNodeType != otherNode.getNodeType())
							return false;
						// If elements, compare 
						if (nextNodeType == Node.ELEMENT_NODE) {
							if (!elementsAreEquivalent((Element)node, (Element)otherNode))
								return false;
						}
						// Else if comment, compare
						else if (nextNodeType == Node.COMMENT_NODE) {
							if (!nodeValuesAreEqual(node, otherNode))
								return false;
						}
						// Else punt on other node types
						else {
							return false;
						}
						node = nextNonTextNode(node.getNextSibling());
						otherNode = nextNonTextNode(otherNode.getNextSibling());
					}
					// If also at end of other children, return equal
					if (otherNode == null)
						return true;
				}
			}
		}
		else if (!otherElement.hasChildNodes()) {
			return attributesAreEqual(element, otherElement);
		}
		return false;
	}
	
	private static Node nextNonTextNode(Node node) {
		while (node != null && node.getNodeType() == Node.TEXT_NODE)
			node = node.getNextSibling();
		return node;
	}

	private static boolean attributesAreEqual(Element element, Element otherElement) {
		NamedNodeMap attrs = element.getAttributes();
		NamedNodeMap otherAttrs = otherElement.getAttributes();
		if (attrs == null && otherAttrs == null) {
			// Return comparison of element values if there are no attributes
			return nodeValuesAreEqual(element, otherElement);
		}
		
		if (attrs.getLength() == otherAttrs.getLength()) {
			if (attrs.getLength() == 0)
				// Return comparison of element values if there are no attributes
				return nodeValuesAreEqual(element, otherElement);
			
			for (int i = 0; i < attrs.getLength(); i++) {
				Node attr = attrs.item(i);
				Node otherAttr = otherAttrs.getNamedItem(attr.getNodeName());
				if (!nodeValuesAreEqual(attr, otherAttr))
					return false;
			}
			return true;
		}
		return false;
	}
	
	private static boolean nodeValuesAreEqual(Node node, Node otherNode) {
		String value = node.getNodeValue();
		String otherValue = otherNode.getNodeValue();
		if (value != null && otherValue != null) {
			if (value.equals(otherValue))
				return true;
		}
		else if (value == null && otherValue == null)
			return true;
		return false;
	}
}
