package org.hbbtv.refapp;

import java.io.*;
import java.util.*;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.xml.sax.InputSource;

public class XMLUtil {

	public static Document createDocument(String data) throws IllegalArgumentException {
		return createDocument(new StringReader(data));
	}
	
	public static Document createDocument(InputStream stream) throws IllegalArgumentException {
		return createDocument(new InputSource(stream));
	}
	
	public static Document createDocument(Reader reader) throws IllegalArgumentException {
		return createDocument(new InputSource(reader));
	}
	
	public static Document createDocument(InputSource is) throws IllegalArgumentException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setCoalescing(true);
		factory.setIgnoringComments(true);
		factory.setIgnoringElementContentWhitespace(true);
		factory.setValidating(false);		
		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
			return builder.parse(is);
		} catch (Exception ex) {
			throw new IllegalArgumentException(ex.getMessage(), ex);
		}
	}
	
/***************************************************/

	/**
	 * Get first child element by nodename.
	 * @param parent
	 * @param name	name of element or NULL to return first element
	 * @return	element or null
	 */
	public static Element getChildElement(Element parent, String name) {
		for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
			if (child instanceof Element) {
				if (name!=null) {
					if (name.equals(child.getNodeName()))
						return (Element)child;
				} else {
					return (Element)child;
				}
			}
	    }
	    return null;
	}

	/**
	 * Get all child elements by nodename.
	 * @param parent
	 * @param name
	 * @return	list of elements or empty list
	 */
	public static List<Element> getChildElements(Element parent, String name) {
		List<Element> list = new ArrayList<Element>();
		for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
			if (child instanceof Element && name.equals(child.getNodeName()))
				list.add((Element)child);
	    }
	    return list;
	}
	
	/**
	 * Get text from element. Loop all #text child nodes.
	 * @param element
	 * @param defval	default value if element was null 
	 * @return
	 */
	public static String getText(Element element, String defval) {
		String value = getText(element);
		return (value != null ? value : defval);
	}
	
	/**
	 * Get text from element. Loop all #text child nodes.
	 */
	public static String getText(Element element) {
		if (element == null) return null;
		StringBuilder sb = new StringBuilder();
		NodeList nodes = element.getChildNodes();
		Node node;
		for(int i=0; i < nodes.getLength(); i++) {
			node = nodes.item(i);
			if (node.getNodeType() == Node.TEXT_NODE)
				sb.append(node.getNodeValue());
		}
		return sb.toString().trim();
	}

	/**
	 * Create XML string from dom element tree.
	 * @param elem
	 * @return
	 * @throws Exception
	 */
	public static String createXML(Element elem) throws Exception {
	    DOMSource source = new DOMSource(elem);
	    StringWriter writer = new StringWriter();
	    StreamResult result = new StreamResult(writer);
	    TransformerFactory transformerFactory = TransformerFactory.newInstance();
	    Transformer transformer = transformerFactory.newTransformer();
	    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
	    //transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
	    //transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
	    transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,"yes");
	    transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
	    transformer.transform(source, result);
	    return writer.toString();
	}
	
}

@@ -4305,23 +4305,505 @@
 ;%0D%0A%09    
-return 
+%0D%0A%09    // Java10-transformer adds unecessary empty lines, remove empty lines%0D%0A%09    BufferedReader reader = new BufferedReader(new StringReader(writer.toString()));%0D%0A%09    StringBuilder buf = new StringBuilder();%0D%0A%09    try %7B%0D%0A%09%09    String line;%0D%0A%09%09    while( (line=reader.readLine())!=null ) %7B%0D%0A%09%09    %09if (!line.trim().isEmpty()) %7B%0D%0A%09%09    %09%09buf.append(line); %0D%0A%09%09    %09%09buf.append(Utils.NL);%0D%0A%09%09    %09%7D%0D%0A%09%09    %7D%0D%0A%09    %7D finally %7B%0D%0A%09    %09reader.close();%0D%0A%09    %7D%0D%0A%09    return buf.toString();  //
 writer.t

trim xml empty lines