/**
 * Copyright 2008-2010. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved. <a>http://www.cqcis.com</a>
 */
package com.crunii.micro.common.xml;

import com.crunii.micro.common.exception.BusinessException;
import com.crunii.micro.common.utils.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.util.StringUtils;

import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;

/**
 * @author 田平 create 2015-7-3下午1:43:10
 */
@Slf4j
public class XmlUtil {

	public static String formatXml(String xml, String encoding) {
		Document document = parseXml(xml);
		return generate(document, encoding);
	}

	public static String formatXml(String xml) {
		Document document = parseXml(xml);
		return generate(document);
	}

	public static Document parseXml(String xml) {
		Reader in = new StringReader(xml);
		SAXReader reader = new SAXReader();
		try {
			return reader.read(in);
		} catch (Exception e) {
			throw new BusinessException("XmlUtil parseXml error xml:{}", xml, e);
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (Exception e) {
					throw new BusinessException("XmlUtil parseXml error in.close() xml:{}", xml, e);
				}
			}
		}
	}

	public static Document createDocument() {
		Document document = DocFactory.getInstance().createDocument();
		return document;
	}

	public static Document createDocument(String encoding) {
		Document document = DocFactory.getInstance().createDocument(encoding);

		return document;
	}

	public static String generate(Document document) {
		String encoding = document.getXMLEncoding();
		if (!StringUtils.hasText(encoding)) {
			encoding = StandardCharsets.UTF_8.name();
		}
		return generate(document, encoding);
	}

	/**
	 * 把document转换为格式化的xml字符串
	 *
	 * @param document
	 * @param encoding
	 * @return
	 * @throws Exception
	 */
	public static String generate(Document document, String encoding) {

		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding(encoding);
		format.setNewLineAfterDeclaration(false);
		StringWriter strWriter = new StringWriter();
		XMLWriter writer = new XMLWriter(strWriter, format);

		String xml = null;
		try {
			writer.write(document);
			xml = strWriter.toString();
		} catch (Exception e) {
			log.warn("XmlUtil.generate writer.write error!", e);
			return document.asXML();
		} finally {
			try {
				if (writer != null) {
					writer.close();
				}
				if (strWriter != null) {
					strWriter.close();
				}
			} catch (Exception e2) {
				throw new RuntimeException("XmlUtil.generate writer.close() or strWriter.close() error!", e2);
			}
		}
		return xml;
	}

	public static String getNodeXml(String xml, String nodeName) {
		Node node = getNodeByPath(xml, "//" + nodeName);
		if (node != null) {
			return node.asXML();
		} else {
			return null;
		}

	}

	public static String getNodeXmlByPath(String xml, String xpath) {
		Node node = getNodeByPath(xml, xpath);
		if (node != null) {
			return node.asXML();
		} else {
			return null;
		}
	}

	public static String getNodeTextByPath(String xml, String xpath) {
		Node node = getNodeByPath(xml, xpath);
		if (node != null) {
			return node.getText();
		} else {
			return null;
		}
	}

	public static Node getNodeByPath(String xml, String xpath) {
		if (StringUtils.hasText(xml)) {
			Document document = parseXml(xml);
			Node node = document.selectSingleNode(xpath);
			return node;
		} else {
			return null;
		}
	}

	public static void main(String[] args) {
		String xml = FileUtil.getFileContent("C:\\Users\\Administrator\\Desktop\\test.xml");
		String nodeXml = getNodeTextByPath(xml, "//*[local-name()='out']");
		System.out.println(nodeXml);
	}

}
