//------------------------------------------------------------------------------
// 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 '&':
				sb.append(XML_AMP);
				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);
	}

}