//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.common.utils;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXParseException;

/**
 * Utility class for processing XML documents.
 * 
 * @author Kelvin Low
 * @author Jinhua Xi
 * @since 1.0
 */
public class XMLUtil {

	/**
	 * XML declaration.
	 */
	public final static String XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; //$NON-NLS-1$

	/**
	 * XML Escape characters.
	 */
	public final static String XML_AMP = "&amp;"; //$NON-NLS-1$

	public final static String XML_BACKSLASH = "&#92;"; //$NON-NLS-1$	

	public final static String XML_APOS = "&apos;"; //$NON-NLS-1$

	public final static String XML_CR = "&#13;"; //$NON-NLS-1$

	public final static String XML_GT = "&gt;"; //$NON-NLS-1$

	public final static String XML_LT = "&lt;"; //$NON-NLS-1$

	public final static String XML_LF = "&#10;"; //$NON-NLS-1$	

	public final static String XML_QUOT = "&quot;"; //$NON-NLS-1$

	public final static String XML_TAB = "&#9;"; //$NON-NLS-1$

	private static final String CRLF = "\r\n"; //$NON-NLS-1$

	private static final byte[] CRLF_BYTES = CRLF.getBytes();

	/**
	 * Private constructor to prevent this class from being instantiated. All
	 * methods in this class should be static.
	 */
	private XMLUtil() {
	}

	/**
	 * Clones the given DOM node into the given DOM document.
	 * 
	 * @param node
	 *            The DOM node to clone.
	 * @param doc
	 *            The target DOM document.
	 * @return The cloned node in the target DOM document.
	 */
	public static Node cloneNode(Node node, Document doc) {
		Node clone = null;
		switch (node.getNodeType()) {
		case Node.ELEMENT_NODE:
			clone = doc.createElement(node.getNodeName());
			NamedNodeMap attrs = node.getAttributes();
			for (int i = 0; i < attrs.getLength(); i++) {
				Node attrNode = attrs.item(i);
				Attr attrClone = doc.createAttribute(attrNode.getNodeName());
				attrClone.setNodeValue(attrNode.getNodeValue());
				((Element) clone).setAttributeNode(attrClone);
			}

			// Iterate through each child nodes.
			NodeList childNodes = node.getChildNodes();
			if (childNodes != null) {
				for (int i = 0; i < childNodes.getLength(); i++) {
					Node childNode = childNodes.item(i);
					Node childClone = cloneNode(childNode, doc);
					clone.appendChild(childClone);
				}
			}
			break;

		case Node.TEXT_NODE:
		case Node.CDATA_SECTION_NODE:
			clone = doc.createTextNode(node.getNodeName());
			clone.setNodeValue(node.getNodeValue());
			break;
		}
		return clone;
	}

	/**
	 * Escapes a XML attribute to make it XML parser friendly.
	 * 
	 * @param str
	 *            The XML attribute string.
	 * @return The escaped string.
	 */
	public static String escapeAttr(String str) {
		if (str == null || str.length() == 0)
			return ""; //$NON-NLS-1$
		StringBuffer sb = new StringBuffer();
		int len = str.length();
		for (int i = 0; i < len; i++) {
			char ch = str.charAt(i);
			switch (ch) {
			case '<':
				sb.append(XML_LT);
				break;
			case '&':
				sb.append(XML_AMP);
				break;
			case '"':
				sb.append(XML_QUOT);
				break;
			default:
				sb.append(ch);
				break;
			}
		}
		return sb.toString();
	}

	/**
	 * Escapes the given string to make it XML parser friendly.
	 * 
	 * @param str
	 *            The source string.
	 * @return The escaped string.
	 */
	public static String escape(String str) {
		if (str == null || str.length() == 0)
			return ""; //$NON-NLS-1$
		StringBuffer sb = new StringBuffer();
		int len = str.length();
		for (int i = 0; i < len; i++) {
			char ch = str.charAt(i);
			switch (ch) {
			case '<':
				sb.append(XML_LT);
				break;
			case '>':
				sb.append(XML_GT);
				break;
			case '&':
				sb.append(XML_AMP);
				break;
			case '"':
				sb.append(XML_QUOT);
				break;
			case '\'':
				sb.append(XML_APOS);
				break;
			case '\r':
				sb.append(XML_CR);
				break;
			case '\n':
				sb.append(XML_LF);
				break;
			case '\\':
				sb.append(XML_BACKSLASH);
				break;
			default:
				sb.append(ch);
				break;
			}
		}
		return sb.toString();
	}

	/**
	 * Escapes the given string to make it XML parser friendly.
	 * 
	 * @param str
	 *            The source string.
	 * @param ignoreCRLF
	 *            If true, do not escape the CR and LF characters.
	 * @return The escaped string.
	 */
	public static String escape(String str, boolean ignoreCRLF) {
		if (str == null || str.length() == 0)
			return ""; //$NON-NLS-1$
		StringBuffer sb = new StringBuffer();
		int len = str.length();
		for (int i = 0; i < len; i++) {
			char ch = str.charAt(i);
			switch (ch) {
			case '<':
				sb.append(XML_LT);
				break;
			case '>':
				sb.append(XML_GT);
				break;
			case '&':
				// This is to avoid the double escaping (see Bugzilla 179921)
				if (!str.startsWith(XML_LT+"p/", i) && !str.startsWith(XML_APOS, i) //$NON-NLS-1$ 
						&& !str.startsWith(XML_AMP, i))
					sb.append(XML_AMP);
				else
					sb.append(ch);
				break;
			case '"':
				sb.append(XML_QUOT);
				break;
			case '\'':
				sb.append(XML_APOS);
				break;
			case '\r':
				if (ignoreCRLF)
					sb.append(ch);
				else
					sb.append(XML_CR);
				break;
			case '\n':
				if (ignoreCRLF)
					sb.append(ch);
				else
					sb.append(XML_LF);
				break;
			default:
				sb.append(ch);
				break;
			}
		}
		return sb.toString();
	}

	/**
	 * Unescapes the given XML string.
	 * 
	 * @param str
	 *            The source string.
	 * @return The escaped string.
	 */
	public static String unescape(String str) {
		if (str == null || str.length() == 0)
			return ""; //$NON-NLS-1$
		StringBuffer sb = new StringBuffer();
		int len = str.length();
		for (int i = 0; i < len; i++) {
			char ch = str.charAt(i);
			switch (ch) {
			case '&':
				if (str.startsWith(XML_LT, i)) {
					sb.append('<');
					i += 3;
				} else if (str.startsWith(XML_GT, i)) {
					sb.append('>');
					i += 3;
				} else if (str.startsWith(XML_AMP, i)) {
					sb.append('&');
					i += 4;
				} else if (str.startsWith(XML_QUOT, i)) {
					sb.append('"');
					i += 5;
				} else if (str.startsWith(XML_APOS, i)) {
					sb.append("\'"); //$NON-NLS-1$
					i += 5;
				} else if (str.startsWith(XML_CR, i)) {
					sb.append('\r');
					i += 4;
				} else if (str.startsWith(XML_LF, i)) {
					sb.append('\n');
					i += 4;
				} else {
					sb.append(ch);
				}
				break;
			default:
				sb.append(ch);
				break;
			}
		}
		return sb.toString();
	}

	/**
	 * Writes the content of the given DOM document to the output stream.
	 * 
	 * @param xmlDoc
	 *            The DOM document.
	 * @param output
	 *            The output stream.
	 * @throws IOException
	 *             if an I/O error occur while accessing the output stream.
	 */
	public static void writeDocument(Document xmlDoc, OutputStream output)
			throws IOException {
		DataOutputStream out = new DataOutputStream(output);
		writeNode(xmlDoc, "", out); //$NON-NLS-1$
		out.flush();
	}

	/**
	 * Writes the content of the given DOM document to the PrintWriter.
	 * 
	 * @param xmlDoc
	 *            The DOM document.
	 * @param pw
	 *            The PrintWriter object.
	 * @throws IOException
	 *             if an I/O error occur while accessing the output stream.
	 */
	public static void writeDocument(Document xmlDoc, PrintWriter pw)
			throws IOException {
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		DataOutputStream out = new DataOutputStream(os);
		writeNode(xmlDoc, "", out); //$NON-NLS-1$
		out.flush();
		// FIXME! Need to specify encoding?
		String s = os.toString();
		pw.write(s);
		pw.flush();
	}

	/**
	 * Saves the content of the given DOM document to file.
	 * 
	 * @param xmlDoc
	 *            The DOM document.
	 * @param xmlFile
	 *            The XML file.
	 * @throws IOException
	 *             if an I/O error occur while accessing the output stream.
	 */
	public static void saveDocument(Document xmlDoc, String xmlFile)
			throws IOException {
		DataOutputStream out = new DataOutputStream(new FileOutputStream(
				xmlFile));
		writeNode(xmlDoc, "", out); //$NON-NLS-1$
		out.flush();
		out.close();
	}

	/**
	 * Saves the given XML string to the given file.
	 * 
	 * @param xmlStr
	 *            The XML string.
	 * @param xmlFile
	 *            The XML file.
	 * @throws IOException
	 *             if an I/O error occur while accessing the output stream.
	 */
	public static void saveDocument(String xmlStr, String xmlFile)
			throws IOException {
		DataOutputStream out = new DataOutputStream(new FileOutputStream(
				xmlFile));
		out.write(xmlStr.getBytes());
		out.flush();
		out.close();
	}

	/**
	 * Writes the given DOM tree node to the given output stream.
	 * 
	 * @param node
	 *            The DOM node.
	 * @param indent
	 *            The string indentation (containing space characters).
	 * @param out
	 *            The output stream.
	 * @throws IOException
	 *             if an I/O error occur while accessing the output stream.
	 */
	private static void writeNode(Node node, String indent, DataOutputStream out)
			throws IOException {
		String text;

		switch (node.getNodeType()) {
		case Node.DOCUMENT_NODE:
			// Write the XML file signature.
			out.write(StrUtil.getUTF8Bytes(XML_DECLARATION));
			out.write(CRLF_BYTES);

			// Iterate through each child nodes.
			NodeList nodes = node.getChildNodes();
			if (nodes != null) {
				for (int i = 0; i < nodes.getLength(); i++) {
					writeNode(nodes.item(i), "", out); //$NON-NLS-1$
				}
			}
			break;

		case Node.ELEMENT_NODE:
			String name = node.getNodeName();
			out.write(StrUtil.getUTF8Bytes(indent + "<" + name)); //$NON-NLS-1$
			NamedNodeMap attrs = node.getAttributes();
			for (int i = 0; i < attrs.getLength(); i++) {
				Node attrNode = attrs.item(i);
				out.write(StrUtil.getUTF8Bytes(" " + attrNode.getNodeName() //$NON-NLS-1$
						+ "=\"" + escape(attrNode.getNodeValue()) + "\"")); //$NON-NLS-1$ //$NON-NLS-2$
			}
			out.write(StrUtil.getUTF8Bytes(">")); //$NON-NLS-1$
			out.write(CRLF_BYTES);

			// Iterate through each child nodes.
			NodeList childNodes = node.getChildNodes();
			if (childNodes != null) {
				for (int i = 0; i < childNodes.getLength(); i++) {
					writeNode(childNodes.item(i), indent, out);
				}
			}
			out.write(StrUtil.getUTF8Bytes(indent + "</" + name + ">")); //$NON-NLS-1$ //$NON-NLS-2$
			out.write(CRLF_BYTES);

			break;

		case Node.TEXT_NODE:
			text = StrUtil.removeWhiteSpaceChars(node.getNodeValue());
			if (text.length() > 0) {
				out.write(StrUtil.getUTF8Bytes(escape(text)));
			}
			break;

		case Node.CDATA_SECTION_NODE:
			text = StrUtil.removeWhiteSpaceChars(node.getNodeValue());
			if (text.length() > 0) {
				out.write(StrUtil.getUTF8Bytes("<![CDATA[")); //$NON-NLS-1$
				out.write(StrUtil.getUTF8Bytes(text));
				out.write(StrUtil.getUTF8Bytes("]]>")); //$NON-NLS-1$
				out.write(CRLF_BYTES);
			}
			break;

		case Node.PROCESSING_INSTRUCTION_NODE:
			out.write(StrUtil.getUTF8Bytes("<?" + node.getNodeName() //$NON-NLS-1$
					+ " " + node.getNodeValue() + "?>")); //$NON-NLS-1$ //$NON-NLS-2$
			out.write(CRLF_BYTES);
			break;

		case Node.ENTITY_REFERENCE_NODE:
			out.write(StrUtil.getUTF8Bytes("&" + node.getNodeName() + ";")); //$NON-NLS-1$ //$NON-NLS-2$
			break;
		}
	}

	/**
	 * Returns the file location where the given SAX exception occurred.
	 * 
	 * @param e
	 *            The SAX parse exception.
	 * @return A string containing the file location where the exception
	 *         occurred.
	 */
	public static String getLocationOfException(SAXParseException e) {
		StringBuffer sb = new StringBuffer();
		sb.append("row "); //$NON-NLS-1$
		sb.append(e.getLineNumber());
		sb.append(", col "); //$NON-NLS-1$
		sb.append(e.getColumnNumber());

		String systemId = e.getSystemId();
		if (systemId != null) {
			int index = systemId.lastIndexOf('/');
			if (index != -1) {
				systemId = systemId.substring(index + 1);
			}
			sb.append(" of XML document "); //$NON-NLS-1$
			sb.append(systemId);
		}

		return sb.toString();
	}

	public static Document loadXml(File file) throws Exception {
		DocumentBuilderFactory builderFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder builder = builderFactory.newDocumentBuilder();

		return builder.parse(file);
	}

	public static Document createDocument() throws Exception {
		DocumentBuilderFactory builderFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder builder = builderFactory.newDocumentBuilder();
		return builder.newDocument();
	}

	/**
	 * text of a leaf node, without child element
	 * 
	 * @param tag
	 * @return String
	 */
	public static String getNodeText(Element tag) {
		String text = tag.toString();
		int i = text.indexOf(">"); //$NON-NLS-1$
		int j = text.lastIndexOf("</"); //$NON-NLS-1$
		if (i < 0 || j < 0 || j < i) {
			return ""; //$NON-NLS-1$
		}

		return text.substring(i + 1, j);
	}

	public static String getChildText(Element tag, String childTagName) {
		Element child = getFirstChild(tag, childTagName);
		if (child != null) {
			return getNodeText(child);
		}

		return ""; //$NON-NLS-1$
	}

	public static Element getFirstChild(Element tag, String childTagName) {
		NodeList nodes = tag.getElementsByTagName(childTagName);
		if (nodes == null || nodes.getLength() == 0) {
			return null;
		}

		return (Element) nodes.item(0);
	}

	/**
	 * iterator of all the children of the element
	 * 
	 * @param tag
	 * @return Iterator
	 */
	public static Iterator childIterator(Element tag) {
		NodeList nodes = tag.getChildNodes();

		// NodeList contains no Element nodes such as text nodes, ignore those
		List<Node> elements = new ArrayList<Node>();
		if (nodes != null) {
			int size = nodes.getLength();
			for (int i = 0; i < size; i++) {
				Node node = nodes.item(i);
				if (node instanceof Element) {
					elements.add(node);
				}
			}
		}

		return elements.iterator();
	}

	private static class NodeIterator implements Iterator {
		int currentIndex = -1;

		int size = 0;

		NodeList nodes = null;

		public NodeIterator(NodeList nodes) {
			this.nodes = nodes;
			if (nodes != null)
				size = nodes.getLength();
		}

		public void remove() {
			// Do nothing, this is a readonly iterator.
		}

		public boolean hasNext() {
			return currentIndex + 1 < size;
		}

		public Object next() {
			if (hasNext()) {
				return nodes.item(++currentIndex);
			}

			return null;
		}
	}

	/**
	 * iterator of all the children of the element
	 * 
	 * @param tag
	 * @return Iterator
	 */
	public static Iterator childIterator(Element tag, String childTagName) {
		NodeList nodes = tag.getElementsByTagName(childTagName);
		return new NodeIterator(nodes);
	}

}