/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package org.ofbiz.base.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.xerces.parsers.DOMParser;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

/**
 * Utilities methods to simplify dealing with JAXP & DOM XML parsing
 *
 */
public class UtilXml {

    public static final String module = UtilXml.class.getName();
    private static final XStream xstream = createXStream();

    private static XStream createXStream() {
        XStream xstream = new XStream();
        xstream.registerConverter(new UnsupportedClassConverter());
        return xstream;
    }

    // ----- DOM Level 3 Load and Save Methods -- //

    /** Returns a <code>DOMImplementationLS</code> instance.
     * @return A <code>DOMImplementationLS</code> instance
     * @see <a href="http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/">DOM Level 3 Load and Save Specification</a>
     * @throws ClassCastException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static DOMImplementationLS getDomLsImplementation() throws ClassCastException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
        return (DOMImplementationLS)registry.getDOMImplementation("LS");
    }

    /** Returns a <code>LSOutput</code> instance.
     * @param impl A <code>DOMImplementationLS</code> instance
     * @param os Optional <code>OutputStream</code> instance
     * @param encoding Optional character encoding, default is UTF-8
     * @return A <code>LSOutput</code> instance
     * @see <a href="http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/">DOM Level 3 Load and Save Specification</a>
     */
    public static LSOutput createLSOutput(DOMImplementationLS impl, OutputStream os, String encoding) {
        LSOutput out = impl.createLSOutput();
        if (os != null) {
            out.setByteStream(os);
        }
        if (encoding != null) {
            out.setEncoding(encoding);
        }
        return out;
    }

    /** Returns a <code>LSSerializer</code> instance.
     * @param impl A <code>DOMImplementationLS</code> instance
     * @param includeXmlDeclaration If set to <code>true</code>,
     * the xml declaration will be included in the output
     * @param enablePrettyPrint If set to <code>true</code>, the
     * output will be formatted in human-readable form. If set to
     * <code>false</code>, the entire document will consist of a single line.
     * @return A <code>LSSerializer</code> instance
     * @see <a href="http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/">DOM Level 3 Load and Save Specification</a>
     */
    public static LSSerializer createLSSerializer(DOMImplementationLS impl, boolean includeXmlDeclaration, boolean enablePrettyPrint) {
        LSSerializer writer = impl.createLSSerializer();
        DOMConfiguration domConfig = writer.getDomConfig();
        domConfig.setParameter("xml-declaration", includeXmlDeclaration);
        domConfig.setParameter("format-pretty-print", enablePrettyPrint);
        return writer;
    }

    /** Serializes a DOM Node to an <code>OutputStream</code> using DOM 3.
     * @param os The <code>OutputStream</code> instance to write to
     * @param node The DOM <code>Node</code> object to be serialized
     * @param encoding Optional character encoding
     * @param includeXmlDeclaration If set to <code>true</code>,
     * the xml declaration will be included in the output
     * @param enablePrettyPrint If set to <code>true</code>, the
     * output will be formatted in human-readable form. If set to
     * <code>false</code>, the entire document will consist of a single line.
     * @see <a href="http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/">DOM Level 3 Load and Save Specification</a>
     * @throws ClassCastException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static void writeXmlDocument(OutputStream os, Node node, String encoding, boolean includeXmlDeclaration, boolean enablePrettyPrint) throws ClassCastException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        DOMImplementationLS impl = getDomLsImplementation();
        LSOutput out = createLSOutput(impl, os, encoding);
        LSSerializer writer = createLSSerializer(impl, includeXmlDeclaration, enablePrettyPrint);
        writer.write(node, out);
    }

    // ----- TrAX Methods ----------------- //

    /** Creates a JAXP TrAX Transformer suitable for pretty-printing an
     * XML document. This method is provided as an alternative to the
     * deprecated <code>org.apache.xml.serialize.OutputFormat</code> class.
     * @param encoding Optional encoding, defaults to UTF-8
     * @param omitXmlDeclaration If <code>true</code> the xml declaration
     * will be omitted from the output
     * @param indent If <code>true</code>, the output will be indented
     * @param indentAmount If <code>indent</code> is <code>true</code>,
     * the number of spaces to indent. Default is 4.
     * @return A <code>Transformer</code> instance
     * @see <a href="http://java.sun.com/javase/6/docs/api/javax/xml/transform/package-summary.html">JAXP TrAX</a>
     * @throws TransformerConfigurationException
     */
    public static Transformer createOutputTransformer(String encoding, boolean omitXmlDeclaration, boolean indent, int indentAmount) throws TransformerConfigurationException {
        // Developers: This stylesheet strips all formatting space characters from the XML,
        // then indents the XML using the specified indentation.
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        sb.append("<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:xalan=\"http://xml.apache.org/xslt\" version=\"1.0\">\n");
        sb.append("<xsl:output method=\"xml\" encoding=\"");
        sb.append(encoding == null ? "UTF-8" : encoding);
        sb.append("\"");
        if (omitXmlDeclaration) {
            sb.append(" omit-xml-declaration=\"yes\"");
        }
        sb.append(" indent=\"");
        sb.append(indent ? "yes" : "no");
        sb.append("\"");
        if (indent) {
            sb.append(" xalan:indent-amount=\"");
            sb.append(indentAmount <= 0 ? 4 : indentAmount);
            sb.append("\"");
        }
        sb.append("/>\n<xsl:strip-space elements=\"*\"/>\n");
        sb.append("<xsl:template match=\"@*|node()\">\n");
        sb.append("<xsl:copy><xsl:apply-templates select=\"@*|node()\"/></xsl:copy>\n");
        sb.append("</xsl:template>\n</xsl:stylesheet>\n");
        ByteArrayInputStream bis = new ByteArrayInputStream(sb.toString().getBytes());
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        return transformerFactory.newTransformer(new StreamSource(bis));
    }

    /** Serializes a DOM <code>Node</code> to an <code>OutputStream</code>
     * using JAXP TrAX.
     * @param transformer A <code>Transformer</code> instance
     * @param node The <code>Node</code> to serialize
     * @param os The <code>OutputStream</code> to serialize to
     * @see <a href="http://java.sun.com/javase/6/docs/api/javax/xml/transform/package-summary.html">JAXP TrAX</a>
     * @throws TransformerException
     */
    public static void transformDomDocument(Transformer transformer, Node node, OutputStream os) throws TransformerException {
        DOMSource source = new DOMSource(node);
        StreamResult result = new StreamResult(os);
        transformer.transform(source, result);
    }

    /** Serializes a DOM <code>Node</code> to an <code>OutputStream</code>
     * using JAXP TrAX.
     * @param node The <code>Node</code> to serialize
     * @param os The <code>OutputStream</code> to serialize to
     * @param encoding Optional encoding, defaults to UTF-8
     * @param omitXmlDeclaration If <code>true</code> the xml declaration
     * will be omitted from the output
     * @param indent If <code>true</code>, the output will be indented
     * @param indentAmount If <code>indent</code> is <code>true</code>,
     * the number of spaces to indent. Default is 4.
     * @see <a href="http://java.sun.com/javase/6/docs/api/javax/xml/transform/package-summary.html">JAXP TrAX</a>
     * @throws TransformerException
     */
    public static void writeXmlDocument(Node node, OutputStream os, String encoding, boolean omitXmlDeclaration, boolean indent, int indentAmount) throws TransformerException {
        Transformer transformer = createOutputTransformer(encoding, omitXmlDeclaration, indent, indentAmount);
        transformDomDocument(transformer, node, os);
    }

    // ----- Java Object Marshalling/Unmarshalling ----- //

    /** Deserialize an object from an <code>InputStream</code>.
     * 
     * @param input The <code>InputStream</code>
     * @return The deserialized <code>Object</code>
     */
    public static Object fromXml(InputStream input) {
        return xstream.fromXML(input);
    }

    /** Deserialize an object from a <code>Reader</code>.
     * 
     * @param reader The <code>Reader</code>
     * @return The deserialized <code>Object</code>
     */
    public static Object fromXml(Reader reader) {
        return xstream.fromXML(reader);
    }

    /** Deserialize an object from a <code>String</code>.
     * 
     * @param str The <code>String</code>
     * @return The deserialized <code>Object</code>
     */
    public static Object fromXml(String str) {
        return xstream.fromXML(str);
    }

    /** Serialize an object to an XML <code>String</code>.
     * 
     * @param obj The object to serialize
     * @return An XML <code>String</code>
     */
    public static String toXml(Object obj) {
        return xstream.toXML(obj);
    }

    /** Serialize an object to an <code>OutputStream</code>.
     * 
     * @param obj The object to serialize
     * @param output The <code>OutputStream</code>
     */
    public static void toXml(Object obj, OutputStream output) {
        xstream.toXML(obj, output);
    }

    /** Serialize an object to a <code>Writer</code>.
     * 
     * @param obj The object to serialize
     * @param writer The <code>Writer</code>
     */
    public static void toXml(Object obj, Writer writer) {
        xstream.toXML(obj, writer);
    }

    // ------------------------------------------------- //

    public static String writeXmlDocument(Node node) throws java.io.IOException {
        if (node == null) {
            Debug.logWarning("[UtilXml.writeXmlDocument] Node was null, doing nothing", module);
            return null;
        }
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        writeXmlDocument(bos, node);
        return bos.toString("UTF-8");
    }

    public static void writeXmlDocument(String filename, Node node) throws FileNotFoundException, IOException {
        if (node == null) {
            Debug.logWarning("[UtilXml.writeXmlDocument] Node was null, doing nothing", module);
            return;
        }
        if (filename == null) {
            Debug.logWarning("[UtilXml.writeXmlDocument] Filename was null, doing nothing", module);
            return;
        }
        File outFile = new File(filename);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(outFile);
            writeXmlDocument(fos, node);
        } finally {
            if (fos != null) {
                fos.close();
            }
        }
    }

    public static void writeXmlDocument(OutputStream os, Node node) throws java.io.IOException {
        if (node == null) {
            Debug.logWarning("[UtilXml.writeXmlDocument] Node was null, doing nothing", module);
            return;
        }
        // OutputFormat defaults are: indent on, indent = 4, include XML declaration,
        // charset = UTF-8, line width = 72
        try {
            writeXmlDocument(node, os, "UTF-8", false, true, 4);
        } catch (TransformerException e) {
            // Wrapping this exception for backwards compatibility
            throw new IOException(e.getMessage());
        }
    }

    public static Document readXmlDocument(String content)
            throws SAXException, ParserConfigurationException, java.io.IOException {
        return readXmlDocument(content, true);
    }

    public static Document readXmlDocument(String content, boolean validate)
            throws SAXException, ParserConfigurationException, java.io.IOException {
        if (content == null) {
            Debug.logWarning("[UtilXml.readXmlDocument] content was null, doing nothing", module);
            return null;
        }
        ByteArrayInputStream bis = new ByteArrayInputStream(content.getBytes("UTF-8"));
        return readXmlDocument(bis, validate, "Internal Content");
    }

    public static Document readXmlDocument(String content, boolean validate, boolean withPosition)
            throws SAXException, ParserConfigurationException, java.io.IOException {
        if (content == null) {
            Debug.logWarning("[UtilXml.readXmlDocument] content was null, doing nothing", module);
            return null;
        }
        ByteArrayInputStream bis = new ByteArrayInputStream(content.getBytes("UTF-8"));
        return readXmlDocument(bis, validate, "Internal Content", withPosition);
    }

    public static Document readXmlDocument(URL url)
            throws SAXException, ParserConfigurationException, java.io.IOException {
        return readXmlDocument(url, true);
    }

    public static Document readXmlDocument(URL url, boolean validate)
            throws SAXException, ParserConfigurationException, java.io.IOException {
        if (url == null) {
            Debug.logWarning("[UtilXml.readXmlDocument] URL was null, doing nothing", module);
            return null;
        }
        InputStream is = url.openStream();
        Document document = readXmlDocument(is, validate, url.toString());
        is.close();
        return document;
    }

    public static Document readXmlDocument(URL url, boolean validate, boolean withPosition)
            throws SAXException, ParserConfigurationException, java.io.IOException {
        if (url == null) {
            Debug.logWarning("[UtilXml.readXmlDocument] URL was null, doing nothing", module);
            return null;
        }
        InputStream is = url.openStream();
        Document document = readXmlDocument(is, validate, url.toString(), withPosition);
        is.close();
        return document;
    }

    public static Document readXmlDocument(InputStream is, String docDescription)
            throws SAXException, ParserConfigurationException, java.io.IOException {
        return readXmlDocument(is, true, docDescription);
    }

    public static Document readXmlDocument(InputStream is, String docDescription, boolean withPosition)
            throws SAXException, ParserConfigurationException, java.io.IOException {
        return readXmlDocument(is, true, docDescription, withPosition);
    }

    public static Document readXmlDocument(InputStream is, boolean validate, String docDescription)
            throws SAXException, ParserConfigurationException, java.io.IOException {
        if (is == null) {
            Debug.logWarning("[UtilXml.readXmlDocument] InputStream was null, doing nothing", module);
            return null;
        }

        long startTime = System.currentTimeMillis();

        // DON'T do this: seems to be causing problems with Catalina/Tomcat, maybe it is expecting a different parser?
        //System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");

        Document document = null;

        /* Xerces DOMParser direct interaction; the other seems to be working better than this, so we'll stay with the standard JAXP stuff
        DOMParser parser = new DOMParser();
        try {
            parser.setFeature("http://xml.org/sax/features/validation", true);
            parser.setFeature("http://apache.org/xml/features/validation/schema", true);
        } catch (SAXException e) {
            Debug.logWarning("Could not set parser feature: " + e.toString(), module);
        }
        parser.parse(new InputSource(is));
        document = parser.getDocument();
        */

        /* Standard JAXP (mostly), but doesn't seem to be doing XML Schema validation, so making sure that is on... */
        DocumentBuilderFactory factory = new org.apache.xerces.jaxp.DocumentBuilderFactoryImpl();
        factory.setValidating(validate);
        factory.setNamespaceAware(true);

        factory.setAttribute("http://xml.org/sax/features/validation", validate);
        factory.setAttribute("http://apache.org/xml/features/validation/schema", validate);

        // with a SchemaUrl, a URL object
        //factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
        //factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", SchemaUrl);
        DocumentBuilder builder = factory.newDocumentBuilder();
        if (validate) {
            LocalResolver lr = new LocalResolver(new DefaultHandler());
            ErrorHandler eh = new LocalErrorHandler(docDescription, lr);

            builder.setEntityResolver(lr);
            builder.setErrorHandler(eh);
        }
        document = builder.parse(is);

        double totalSeconds = (System.currentTimeMillis() - startTime)/1000.0;
        if (Debug.verboseOn()) Debug.logVerbose("XML Read " + totalSeconds + "s: " + docDescription, module);
        return document;
    }

    public static Document readXmlDocument(InputStream is, boolean validate, String docDescription, boolean withPosition)
            throws SAXException, ParserConfigurationException, java.io.IOException {
        if (!withPosition) {
            return readXmlDocument(is, validate, docDescription);
        }

        if (is == null) {
            Debug.logWarning("[UtilXml.readXmlDocument] InputStream was null, doing nothing", module);
            return null;
        }

        long startTime = System.currentTimeMillis();

        Document document = null;

        DOMParser parser = new DOMParser() {
            private XMLLocator locator;

            private void setLineColumn(Node node) {
                if (node.getUserData("startLine") != null) {
                    return;
                }
                node.setUserData("systemId",locator.getLiteralSystemId(), null);
                node.setUserData("startLine",locator.getLineNumber(), null);
                node.setUserData("startColumn",locator.getColumnNumber(), null);
            }

            private void setLineColumn() {
                try {
                    Node node = (Node) getProperty("http://apache.org/xml/properties/dom/current-element-node");
                    if (node != null) {
                        setLineColumn(node);
                    }
                } catch (SAXException ex) {
                    Debug.logWarning(ex, module);
                }
            }

            private void setLastChildLineColumn() {
                try {
                    Node node = (Node) getProperty("http://apache.org/xml/properties/dom/current-element-node");
                    if (node != null) {
                       setLineColumn(node.getLastChild());
                    }
                } catch (SAXException ex) {
                    Debug.logWarning(ex, module);
                }
            }

            @Override
            public void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException {
                super.startGeneralEntity(name, identifier, encoding, augs);
                setLineColumn();
            }

            @Override
            public void comment(XMLString text, Augmentations augs) throws XNIException {
                super.comment(text, augs);
                setLastChildLineColumn();
            }

            @Override
            public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException {
                super.processingInstruction(target, data, augs);
                setLastChildLineColumn();
            }

            @Override
            public void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, Augmentations augs) throws XNIException {
                super.startDocument(locator, encoding, namespaceContext, augs);
                this.locator = locator;
                setLineColumn();
            }

            @Override
            public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) throws XNIException {
                super.doctypeDecl(rootElement, publicId, systemId, augs);
            }

            @Override
            public void startElement(QName elementQName, XMLAttributes attrList, Augmentations augs) throws XNIException {
                super.startElement(elementQName, attrList, augs);
                setLineColumn();
            }

            @Override
            public void characters(XMLString text, Augmentations augs) throws XNIException {
                super.characters(text, augs);
                setLastChildLineColumn();
            }

            @Override
            public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
                super.ignorableWhitespace(text, augs);
                setLastChildLineColumn();
            }
        };
        parser.setFeature("http://xml.org/sax/features/namespaces", true);
        parser.setFeature("http://xml.org/sax/features/validation", validate);
        parser.setFeature("http://apache.org/xml/features/validation/schema", validate);
        parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);

        // with a SchemaUrl, a URL object
        //factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
        //factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", SchemaUrl);
        if (validate) {
            LocalResolver lr = new LocalResolver(new DefaultHandler());
            ErrorHandler eh = new LocalErrorHandler(docDescription, lr);

            parser.setEntityResolver(lr);
            parser.setErrorHandler(eh);
        }
        InputSource inputSource = new InputSource(is);
        inputSource.setSystemId(docDescription);
        parser.parse(inputSource);
        document = parser.getDocument();

        double totalSeconds = (System.currentTimeMillis() - startTime)/1000.0;
        if (Debug.verboseOn()) Debug.logVerbose("XML Read " + totalSeconds + "s: " + docDescription, module);
        return document;
    }

    public static Document makeEmptyXmlDocument() {
        return makeEmptyXmlDocument(null);
    }

    public static Document makeEmptyXmlDocument(String rootElementName) {
        Document document = null;
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        factory.setValidating(true);
        // factory.setNamespaceAware(true);
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();

            document = builder.newDocument();
        } catch (Exception e) {
            Debug.logError(e, module);
        }

        if (document == null) return null;

        if (rootElementName != null) {
            Element rootElement = document.createElement(rootElementName);
            document.appendChild(rootElement);
        }

        return document;
    }

    /** Creates a child element with the given name and appends it to the element child node list. */
    public static Element addChildElement(Element element, String childElementName, Document document) {
        Element newElement = document.createElement(childElementName);

        element.appendChild(newElement);
        return newElement;
    }

    /** Creates a child element with the given name and appends it to the element child node list.
     *  Also creates a Text node with the given value and appends it to the new elements child node list.
     */
    public static Element addChildElementValue(Element element, String childElementName,
            String childElementValue, Document document) {
        Element newElement = addChildElement(element, childElementName, document);

        newElement.appendChild(document.createTextNode(childElementValue));
        return newElement;
    }

    /** Creates a child element with the given namespace supportive name and appends it to the element child node list. */
    public static Element addChildElementNSElement(Element element, String childElementName,
            Document document, String nameSpaceUrl) {
        Element newElement = document.createElementNS(nameSpaceUrl, childElementName);
        element.appendChild(newElement);
        return element;
    }

    /** Creates a child element with the given namespace supportive name and appends it to the element child node list.
     *  Also creates a Text node with the given value and appends it to the new elements child node list.
     */
    public static Element addChildElementNSValue(Element element, String childElementName,
            String childElementValue, Document document, String nameSpaceUrl) {
        Element newElement = document.createElementNS(nameSpaceUrl, childElementName);
        newElement.appendChild(document.createTextNode(childElementValue));
        element.appendChild(newElement);
        return element;
    }

    /** Creates a child element with the given name and appends it to the element child node list.
     *  Also creates a CDATASection node with the given value and appends it to the new elements child node list.
     */
    public static Element addChildElementCDATAValue(Element element, String childElementName,
            String childElementValue, Document document) {
        Element newElement = addChildElement(element, childElementName, document);

        newElement.appendChild(document.createCDATASection(childElementValue));
        return newElement;
    }

    /** Return a List of Element objects that are children of the given element */
    public static List<? extends Element> childElementList(Element element) {
        if (element == null) return null;

        List<Element> elements = new LinkedList<Element>();
        Node node = element.getFirstChild();

        if (node != null) {
            do {
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element childElement = (Element) node;
                    elements.add(childElement);
                }
            } while ((node = node.getNextSibling()) != null);
        }
        return elements;
    }

    /** Return a List of Element objects that have the given name and are
     * immediate children of the given element; if name is null, all child
     * elements will be included. */
    public static List<? extends Element> childElementList(Element element, String childElementName) {
        if (element == null) return null;

        List<Element> elements = new LinkedList<Element>();
        Node node = element.getFirstChild();

        if (node != null) {
            do {
                if (node.getNodeType() == Node.ELEMENT_NODE && (childElementName == null ||
                        childElementName.equals(node.getNodeName()))) {
                    Element childElement = (Element) node;

                    elements.add(childElement);
                }
            } while ((node = node.getNextSibling()) != null);
        }
        return elements;
    }

    /** Return a List of Element objects that have the given name and are
     * immediate children of the given element; if name is null, all child
     * elements will be included. */
    public static List<? extends Element> childElementList(Element element, Set<String> childElementNames) {
        if (element == null) return null;

        List<Element> elements = new LinkedList<Element>();
        if (childElementNames == null) return elements;
        Node node = element.getFirstChild();

        if (node != null) {
            do {
                if (node.getNodeType() == Node.ELEMENT_NODE && childElementNames.contains(node.getNodeName())) {
                    Element childElement = (Element) node;
                    elements.add(childElement);
                }
            } while ((node = node.getNextSibling()) != null);
        }
        return elements;
    }

    /** Return a List of Element objects that have the given name and are
     * immediate children of the given element; if name is null, all child
     * elements will be included. */
    public static List<? extends Element> childElementList(Element element, String... childElementNames) {
        return childElementList(element, UtilMisc.toSetArray(childElementNames));
    }

    /** Return a List of Element objects that are children of the given DocumentFragment */
    public static List<? extends Element> childElementList(DocumentFragment fragment) {
        if (fragment == null) return null;
        List<Element> elements = new LinkedList<Element>();
        Node node = fragment.getFirstChild();
        if (node != null) {
            do {
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element childElement = (Element) node;
                    elements.add(childElement);
                }
            } while ((node = node.getNextSibling()) != null);
        }
        return elements;
    }

    /** Return a List of Node objects that have the given name and are immediate children of the given element;
      * if name is null, all child elements will be included. */
    public static List<? extends Node> childNodeList(Node node) {
        if (node == null) return null;

        List<Node> nodes = new LinkedList<Node>();

        do {
            if (node.getNodeType() == Node.ELEMENT_NODE || node.getNodeType() == Node.COMMENT_NODE) {
                nodes.add(node);
            }
        } while ((node = node.getNextSibling()) != null);
        return nodes;
    }

    /** Return the first child Element
     * returns the first element. */
    public static Element firstChildElement(Element element, Set<String> childElementNames) {
        if (element == null) return null;
        // get the first element with the given name
        Node node = element.getFirstChild();

        if (node != null) {
            do {
                if (node.getNodeType() == Node.ELEMENT_NODE && childElementNames.contains(node.getNodeName())) {
                    Element childElement = (Element) node;

                    return childElement;
                }
            } while ((node = node.getNextSibling()) != null);
        }
        return null;
    }

    /** Return the first child Element
     * returns the first element. */
    public static Element firstChildElement(Element element, String... childElementNames) {
        return firstChildElement(element, UtilMisc.toSetArray(childElementNames));
    }

    /** Return the first child Element
     * returns the first element. */
    public static Element firstChildElement(Element element) {
        if (element == null) return null;
        // get the first element with the given name
        Node node = element.getFirstChild();

        if (node != null) {
            do {
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element childElement = (Element) node;

                    return childElement;
                }
            } while ((node = node.getNextSibling()) != null);
        }
        return null;
    }

    /** Return the first child Element with the given name; if name is null
     * returns the first element. */
    public static Element firstChildElement(Element element, String childElementName) {
        if (element == null) return null;
        if (UtilValidate.isEmpty(childElementName)) return null;
        // get the first element with the given name
        Node node = element.getFirstChild();

        if (node != null) {
            do {
                if (node.getNodeType() == Node.ELEMENT_NODE && (childElementName == null ||
                        childElementName.equals(node.getLocalName() != null ? node.getLocalName() : node.getNodeName()))) {
                    Element childElement = (Element) node;
                    return childElement;
                }
            } while ((node = node.getNextSibling()) != null);
        }
        return null;
    }

    /** Return the first child Element with the given name; if name is null
     * returns the first element. */
    public static Element firstChildElement(Element element, String childElementName, String attrName, String attrValue) {
        if (element == null) return null;
        // get the first element with the given name
        Node node = element.getFirstChild();

        if (node != null) {
            do {
                if (node.getNodeType() == Node.ELEMENT_NODE && (childElementName == null ||
                        childElementName.equals(node.getLocalName() != null ? node.getLocalName() : node.getNodeName()))) {
                    Element childElement = (Element) node;

                    String value = childElement.getAttribute(attrName);

                    if (value != null && value.equals(attrValue)) {
                        return childElement;
                    }
                }
            } while ((node = node.getNextSibling()) != null);
        }
        return null;
    }

    /** Return the text (node value) contained by the named child node. */
    public static String childElementValue(Element element, String childElementName) {
        if (element == null) return null;
        // get the value of the first element with the given name
        Element childElement = firstChildElement(element, childElementName);

        return elementValue(childElement);
    }

    /** Return the text (node value) contained by the named child node or a default value if null. */
    public static String childElementValue(Element element, String childElementName, String defaultValue) {
        if (element == null) return defaultValue;
        // get the value of the first element with the given name
        Element childElement = firstChildElement(element, childElementName);
        String elementValue = elementValue(childElement);

        if (UtilValidate.isEmpty(elementValue))
            return defaultValue;
        else
            return elementValue;
    }

    /** Return a named attribute of a named child node or a default if null. */
    public static String childElementAttribute(Element element, String childElementName, String attributeName, String defaultValue) {
        if (element == null) return defaultValue;
        // get the value of the first element with the given name
        Element childElement = firstChildElement(element, childElementName);
        String elementAttribute = elementAttribute(childElement, attributeName, defaultValue);

        if (UtilValidate.isEmpty(elementAttribute))
            return defaultValue;
        else
            return elementAttribute;
    }


    /** Return the text (node value) of the first node under this, works best if normalized. */
    public static String elementValue(Element element) {
        if (element == null) return null;
        // make sure we get all the text there...
        element.normalize();
        Node textNode = element.getFirstChild();

        if (textNode == null) return null;

        StringBuilder valueBuffer = new StringBuilder();
        do {
            if (textNode.getNodeType() == Node.CDATA_SECTION_NODE || textNode.getNodeType() == Node.TEXT_NODE) {
                valueBuffer.append(textNode.getNodeValue());
            }
        } while ((textNode = textNode.getNextSibling()) != null);
        return valueBuffer.toString();
    }

    /** Return the text (node value) of the first node under this */
    public static String nodeValue(Node node) {
        if (node == null) return null;

        StringBuilder valueBuffer = new StringBuilder();
        do {
            if (node.getNodeType() == Node.CDATA_SECTION_NODE || node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.COMMENT_NODE) {
                valueBuffer.append(node.getNodeValue());
            }
        } while ((node = node.getNextSibling()) != null);
        return valueBuffer.toString();
    }

    public static String elementAttribute(Element element, String attrName, String defaultValue) {
        if (element == null) return defaultValue;
        String attrValue = element.getAttribute(attrName);
        return UtilValidate.isNotEmpty(attrValue) ? attrValue : defaultValue;
    }

    public static String checkEmpty(String string) {
        if (UtilValidate.isNotEmpty(string))
            return string;
        else
            return "";
    }

    public static String checkEmpty(String string1, String string2) {
        if (UtilValidate.isNotEmpty(string1))
            return string1;
        else if (UtilValidate.isNotEmpty(string2))
            return string2;
        else
            return "";
    }

    public static String checkEmpty(String string1, String string2, String string3) {
        if (UtilValidate.isNotEmpty(string1))
            return string1;
        else if (UtilValidate.isNotEmpty(string2))
            return string2;
        else if (UtilValidate.isNotEmpty(string3))
            return string3;
        else
            return "";
    }

    public static boolean checkBoolean(String str) {
        return checkBoolean(str, false);
    }

    public static boolean checkBoolean(String str, boolean defaultValue) {
        if (defaultValue) {
            //default to true, ie anything but false is true
            return !"false".equals(str);
        } else {
            //default to false, ie anything but true is false
            return "true".equals(str);
        }
    }

    public static String nodeNameToJavaName(String nodeName, boolean capitalizeFirst) {
        boolean capitalize = capitalizeFirst;
        StringBuilder sb = new StringBuilder();
        for (int index = 0; index < nodeName.length(); index++) {
            char character = nodeName.charAt(index);
            if ((sb.length() == 0 && !Character.isJavaIdentifierStart(character)) || (sb.length() != 0 && !Character.isJavaIdentifierPart(character))) {
                capitalize = true;
                continue;
            }
            if (sb.length() == 0 && !capitalizeFirst) {
                sb.append(Character.toLowerCase(character));
            } else {
                if (capitalize) {
                    sb.append(Character.toUpperCase(character));
                    capitalize = false;
                } else {
                    sb.append(character);
                }
            }
        }
        return sb.toString();
    }

    /**
     * Local entity resolver to handle J2EE DTDs. With this a http connection
     * to sun is not needed during deployment.
     * Function boolean hadDTD() is here to avoid validation errors in
     * descriptors that do not have a DOCTYPE declaration.
     */
    public static class LocalResolver implements EntityResolver {

        private boolean hasDTD = false;
        private EntityResolver defaultResolver;

        public LocalResolver(EntityResolver defaultResolver) {
            this.defaultResolver = defaultResolver;
        }

        /**
         * Returns DTD inputSource. If DTD was found in the dtds Map and inputSource was created
         * flag hasDTD is set to true.
         * @param publicId - Public ID of DTD
         * @param systemId - System ID of DTD
         * @return InputSource of DTD
         */
        public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
            //Debug.logInfo("resolving XML entity with publicId [" + publicId + "], systemId [" + systemId + "]", module);
            hasDTD = false;
            String dtd = UtilProperties.getSplitPropertyValue(UtilURL.fromResource("localdtds.properties"), publicId);
            if (UtilValidate.isNotEmpty(dtd)) {
                if (Debug.verboseOn()) Debug.logVerbose("[UtilXml.LocalResolver.resolveEntity] resolving DTD with publicId [" + publicId +
                        "], systemId [" + systemId + "] and the dtd file is [" + dtd + "]", module);
                try {
                    URL dtdURL = UtilURL.fromResource(dtd);
                    if (dtdURL == null) {
                        throw new GeneralException("Local DTD not found - " + dtd);
                    }
                    InputStream dtdStream = dtdURL.openStream();
                    InputSource inputSource = new InputSource(dtdStream);

                    inputSource.setPublicId(publicId);
                    hasDTD = true;
                    if (Debug.verboseOn()) Debug.logVerbose("[UtilXml.LocalResolver.resolveEntity] got LOCAL DTD input source with publicId [" +
                            publicId + "] and the dtd file is [" + dtd + "]", module);
                    return inputSource;
                } catch (Exception e) {
                    Debug.logWarning(e, module);
                }
            } else {
                // nothing found by the public ID, try looking at the systemId, or at least the filename part of it and look for that on the classpath
                int lastSlash = systemId.lastIndexOf("/");
                String filename = null;
                if (lastSlash == -1) {
                    filename = systemId;
                } else {
                    filename = systemId.substring(lastSlash + 1);
                }

                URL resourceUrl = UtilURL.fromResource(filename);

                if (resourceUrl != null) {
                    InputStream resStream = resourceUrl.openStream();
                    InputSource inputSource = new InputSource(resStream);

                    if (UtilValidate.isNotEmpty(publicId)) {
                        inputSource.setPublicId(publicId);
                    }
                    hasDTD = true;
                    if (Debug.verboseOn()) Debug.logVerbose("[UtilXml.LocalResolver.resolveEntity] got LOCAL DTD/Schema input source with publicId [" +
                            publicId + "] and the file/resource is [" + filename + "]", module);
                    return inputSource;
                } else {
                    Debug.logWarning("[UtilXml.LocalResolver.resolveEntity] could not find LOCAL DTD/Schema with publicId [" +
                            publicId + "] and the file/resource is [" + filename + "]", module);
                    return null;
                }
            }
            //Debug.logInfo("[UtilXml.LocalResolver.resolveEntity] local resolve failed for DTD with publicId [" +
            //        publicId + "] and the dtd file is [" + dtd + "], trying defaultResolver", module);
            return defaultResolver.resolveEntity(publicId, systemId);
        }

        /**
         * Returns the boolean value to inform id DTD was found in the XML file or not
         * @return boolean - true if DTD was found in XML
         */
        public boolean hasDTD() {
            return hasDTD;
        }
    }


    /** Local error handler for entity resolver to DocumentBuilder parser.
     * Error is printed to output just if DTD was detected in the XML file.
     */
    public static class LocalErrorHandler implements ErrorHandler {

        private String docDescription;
        private LocalResolver localResolver;

        public LocalErrorHandler(String docDescription, LocalResolver localResolver) {
            this.docDescription = docDescription;
            this.localResolver = localResolver;
        }

        public void error(SAXParseException exception) {
            String exceptionMessage = exception.getMessage();
            Pattern valueFlexExpr = Pattern.compile("value '\\$\\{.*\\}'");
            Matcher matcher = valueFlexExpr.matcher(exceptionMessage.toLowerCase());
            if (localResolver.hasDTD() && !matcher.find()) {
                Debug.logError("XmlFileLoader: File "
                    + docDescription
                    + " process error. Line: "
                    + String.valueOf(exception.getLineNumber())
                    + ". Error message: "
                    + exceptionMessage, module
               );
            }
        }

        public void fatalError(SAXParseException exception) {
            if (localResolver.hasDTD()) {
                Debug.logError("XmlFileLoader: File "
                    + docDescription
                    + " process fatal error. Line: "
                    + String.valueOf(exception.getLineNumber())
                    + ". Error message: "
                    + exception.getMessage(), module
               );
            }
        }

        public void warning(SAXParseException exception) {
            if (localResolver.hasDTD()) {
                Debug.logError("XmlFileLoader: File "
                    + docDescription
                    + " process warning. Line: "
                    + String.valueOf(exception.getLineNumber())
                    + ". Error message: "
                    + exception.getMessage(), module
               );
            }
        }
    }

    private static class UnsupportedClassConverter implements Converter {

        @Override
        public boolean canConvert(@SuppressWarnings("rawtypes") Class arg0) {
            if (java.lang.ProcessBuilder.class.equals(arg0)) {
                return true;
            }
            return false;
        }

        @Override
        public void marshal(Object arg0, HierarchicalStreamWriter arg1, MarshallingContext arg2) {
            throw new UnsupportedOperationException();
        }

        @Override
        public Object unmarshal(HierarchicalStreamReader arg0, UnmarshallingContext arg1) {
            throw new UnsupportedOperationException();
        }
    }

}
