/*
 * 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 flex.messaging.config;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import flex.messaging.util.FileUtils;

/**
 * Provides a common base for DOM / XPath based ConfigurationParsers.
 */
public abstract class AbstractConfigurationParser implements ConfigurationParser, ConfigurationConstants, EntityResolver {
    protected ServicesConfiguration config;
    protected DocumentBuilder docBuilder;
    protected ConfigurationFileResolver fileResolver;
    protected TokenReplacer tokenReplacer;

    private Map fileByDocument = new HashMap();

    protected AbstractConfigurationParser() {
        initializeDocumentBuilder();
        tokenReplacer = new TokenReplacer();
    }

    /**
     * Parse the configurations in the configuration file.
     *
     * @param path         the configuration file path
     * @param fileResolver the ConfigurationFileResolver object
     * @param config       the ServicesConfiguration object
     **/
    public void parse(String path, ConfigurationFileResolver fileResolver, ServicesConfiguration config) {
        this.config = config;
        this.fileResolver = fileResolver;
        Document doc = loadDocument(path, fileResolver.getConfigurationFile(path));
        initializeExpressionQuery();
        parseTopLevelConfig(doc);
    }

    /**
     * Report Tokens.
     **/
    public void reportTokens() {
        tokenReplacer.reportTokens();
    }

    protected void initializeDocumentBuilder() {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setIgnoringComments(true);
        factory.setIgnoringElementContentWhitespace(true);

        try {
            docBuilder = factory.newDocumentBuilder();
            docBuilder.setEntityResolver(this);
        } catch (ParserConfigurationException ex) {
            // Error initializing configuration parser.
            ConfigurationException e = new ConfigurationException();
            e.setMessage(PARSER_INIT_ERROR);
            e.setRootCause(ex);
            throw e;
        }
    }

    protected Document loadDocument(String path, InputStream in) {
        try {
            Document doc;

            if (!in.markSupported())
                in = new BufferedInputStream(in);

            // Consume UTF-8 Byte Order Mark (BOM). The InputStream must support mark()
            // as FileUtils.consumeBOM sets a mark for 3 bytes in order to check for a BOM.
            String encoding = FileUtils.consumeBOM(in, null);
            if (FileUtils.UTF_8.equals(encoding) || FileUtils.UTF_16.equals(encoding)) {
                InputSource inputSource = new InputSource(in);
                inputSource.setEncoding(encoding);
                doc = docBuilder.parse(inputSource);
            } else {
                doc = docBuilder.parse(in);
            }

            addFileByDocument(path, doc);
            doc.getDocumentElement().normalize();
            return doc;
        } catch (SAXParseException ex) {
            Integer line = new Integer(ex.getLineNumber());
            Integer col = new Integer(ex.getColumnNumber());
            String message = ex.getMessage();

            // Configuration error on line {line}, column {col}:  '{message}'
            ConfigurationException e = new ConfigurationException();
            e.setMessage(XML_PARSER_ERROR, new Object[]{line, col, message});
            e.setRootCause(ex);
            throw e;
        } catch (SAXException ex) {
            ConfigurationException e = new ConfigurationException();
            e.setMessage(ex.getMessage());
            e.setRootCause(ex);
            throw e;
        } catch (IOException ex) {
            ConfigurationException e = new ConfigurationException();
            e.setMessage(ex.getMessage());
            e.setRootCause(ex);
            throw e;
        }
    }

    protected void addFileByDocument(String path, Node node) {
        String shortPath = path;
        if (shortPath != null && ((shortPath.indexOf('/') != -1) || (shortPath.indexOf("\\") != -1))) {
            int start = 0;
            start = shortPath.lastIndexOf('/');
            if (start == -1) {
                start = shortPath.lastIndexOf("\\");
            }
            shortPath = path.substring(start + 1);
        }
        fileByDocument.put(node, shortPath);
    }

    protected String getSourceFileOf(Node node) {
        return (String) fileByDocument.get(node.getOwnerDocument());
    }

    protected abstract void parseTopLevelConfig(Document doc);

    protected abstract void initializeExpressionQuery();

    protected abstract Node selectSingleNode(Node source, String expression);

    protected abstract NodeList selectNodeList(Node source, String expression);

    protected abstract Object evaluateExpression(Node source, String expression);

    /**
     * Recursively processes all child elements for each of the properties in the provided
     * node list.
     * <p>
     * If a property is a simple element with a text value then it is stored as a String
     * using the element name as the property name. If the same element appears again then
     * the element is converted to a List of values and further occurences are simply added
     * to the List.
     * </p>
     * <p>
     * If a property element has child elements the children are recursively processed
     * and added as a Map.
     * </p>
     * <p>
     * The sourceFileName argument is used as a parameter for token replacement in order
     * to generate a meaningful error message when a token is failed to be replaced.
     * </p>
     *
     * @param properties the NodeList object
     * @return ConfigMap the ConfigMap object
     */
    public ConfigMap properties(NodeList properties) {
        return properties(properties, ConfigurationConstants.UNKNOWN_SOURCE_FILE);
    }

    /**
     * Recursively processes all child elements for each of the properties in the provided
     * node list.
     *
     * @param properties     the NodeList object
     * @param sourceFileName the source file name
     * @return ConfigMap the ConfigMap object
     */
    public ConfigMap properties(NodeList properties, String sourceFileName) {
        int length = properties.getLength();
        ConfigMap map = new ConfigMap(length);

        for (int p = 0; p < length; p++) {
            Node prop = properties.item(p);
            String propName = prop.getNodeName();

            if (propName != null) {
                propName = propName.trim();
                if (prop.getNodeType() == Node.ELEMENT_NODE) {
                    NodeList attributes = selectNodeList(prop, "@*");
                    NodeList children = selectNodeList(prop, "*");
                    if (children.getLength() > 0 || attributes.getLength() > 0) {
                        ConfigMap childMap = new ConfigMap();

                        if (children.getLength() > 0)
                            childMap.addProperties(properties(children, sourceFileName));

                        if (attributes.getLength() > 0)
                            childMap.addProperties(properties(attributes, sourceFileName));

                        map.addProperty(propName, childMap);
                    } else {
                        // replace tokens before setting property
                        tokenReplacer.replaceToken(prop, sourceFileName);
                        String propValue = evaluateExpression(prop, ".").toString();
                        map.addProperty(propName, propValue);
                    }
                } else {
                    // replace tokens before setting property
                    tokenReplacer.replaceToken(prop, sourceFileName);
                    map.addProperty(propName, prop.getNodeValue());
                }
            }
        }

        return map;
    }

    /**
     * Get the item value by name if the item is present in the current node as attribute or child element.
     *
     * @param node the current Node object
     * @param name item name
     * @return String the value of item
     **/
    public String getAttributeOrChildElement(Node node, String name) {
        String attr = evaluateExpression(node, "@" + name).toString().trim();
        if (attr.length() == 0) {
            attr = evaluateExpression(node, name).toString().trim();
        }
        return attr;
    }

    /**
     * Check whether the required items are present in the current node as child elements.
     *
     * @param node    the current Node object
     * @param allowed the String array of the allowed items
     **/
    public void allowedChildElements(Node node, String[] allowed) {
        NodeList children = selectNodeList(node, "*");

        String unexpected = unexpected(children, allowed);
        if (unexpected != null) {
            // Unexpected child element '{0}' found in '{1}'.
            ConfigurationException ex = new ConfigurationException();
            Object[] args = {unexpected, node.getNodeName(), getSourceFilename(node)};
            ex.setMessage(UNEXPECTED_ELEMENT, args);
            throw ex;
        }

        NodeList textNodes = selectNodeList(node, "text()");
        for (int i = 0; i < textNodes.getLength(); i++) {
            String text = evaluateExpression(textNodes.item(i), ".").toString().trim();
            if (text.length() > 0) {
                //Unexpected text '{0}' found in '{1}'.
                ConfigurationException ex = new ConfigurationException();
                Object[] args = {text, node.getNodeName(), getSourceFilename(node)};
                ex.setMessage(UNEXPECTED_TEXT, args);
                throw ex;
            }
        }
    }

    /**
     * Check whether the required items are present in the current node as attributes.
     *
     * @param node    the current Node object
     * @param allowed the String array of the allowed items
     **/

    public void allowedAttributes(Node node, String[] allowed) {
        NodeList attributes = selectNodeList(node, "@*");
        String unexpectedAttribute = unexpected(attributes, allowed);
        if (unexpectedAttribute != null) {
            //Unexpected attribute '{0}' found in '{1}'.
            ConfigurationException ex = new ConfigurationException();
            Object[] args =
                    {unexpectedAttribute, node.getNodeName(), getSourceFilename(node)};
            ex.setMessage(UNEXPECTED_ATTRIBUTE, args);
            throw ex;
        }
    }

    private String getSourceFilename(Node node) {
        return getSourceFileOf(node);
    }

    /**
     * Check whether the allowed items are present in the current node as elements or attributes.
     *
     * @param node    the current Node object
     * @param allowed the String array of the allowed items
     **/

    public void allowedAttributesOrElements(Node node, String[] allowed) {
        allowedAttributes(node, allowed);
        allowedChildElements(node, allowed);
    }

    /**
     * Check whether the required items are present in the current node as elements or attributes.
     *
     * @param node     the current Node object
     * @param required the String array of the required items
     **/
    public void requiredAttributesOrElements(Node node, String[] required) {
        String nodeName = node.getNodeName();
        NodeList attributes = selectNodeList(node, "@*");

        List list = new ArrayList();
        for (int i = 0; i < required.length; i++) {
            list.add(required[i]);
        }

        String missingAttribute = null;

        do {
            missingAttribute = required(attributes, list);
            if (missingAttribute != null) {
                Node child = selectSingleNode(node, missingAttribute);
                if (child != null) {
                    list.remove(missingAttribute);
                } else {
                    // Attribute '{0}' must be specified for element '{1}'
                    ConfigurationException ex = new ConfigurationException();
                    ex.setMessage(MISSING_ATTRIBUTE, new Object[]{missingAttribute, nodeName});
                    throw ex;
                }
            }
        }
        while (missingAttribute != null && list.size() > 0);
    }

    /**
     * Check whether the required items are present in the current node (Child elements).
     *
     * @param node     the current Node object
     * @param required the String array of the required items
     **/
    public void requiredChildElements(Node node, String[] required) {
        String nodeName = node.getNodeName();
        NodeList children = selectNodeList(node, "*");

        List list = new ArrayList();
        for (int i = 0; i < required.length; i++) {
            list.add(required[i]);
        }

        String missing = required(children, list);
        if (missing != null) {
            // Child element '{0}' must be specified for element '{1}'
            ConfigurationException ex = new ConfigurationException();
            ex.setMessage(MISSING_ELEMENT, new Object[]{missing, nodeName});
            throw ex;
        }
    }

    /**
     * Check whether there is any unexpected item in the node list object.
     *
     * @param attributes the current NodeList object
     * @param allowed,   the String array of allowed items
     * @return Name of the first unexpected item from the list of allowed attributes, or null if all
     * items present were allowed.
     **/
    public String unexpected(NodeList attributes, String[] allowed) {
        for (int i = 0; i < attributes.getLength(); i++) {
            Node attrib = attributes.item(i);
            String attribName = attrib.getNodeName();
            boolean match = false;

            for (int j = 0; j < allowed.length; j++) {
                String a = allowed[j];
                if (a.equals(attribName)) {
                    match = true;
                    break;
                }
            }

            if (!match) {
                return attribName;
            }

            // Go ahead and replace tokens in node values.
            tokenReplacer.replaceToken(attrib, getSourceFilename(attrib));
        }

        return null;
    }

    /**
     * Check whether all the required items are present in the node list.
     *
     * @param attributes the NodeList object
     * @param required   a list of required items
     * @return Name of the first missing item from the list of required attributes, or null if all required
     * items were present.
     **/
    public String required(NodeList attributes, List required) {
        for (int i = 0; i < required.size(); i++) {
            boolean found = false;
            String req = (String) required.get(i);

            Node attrib = null;
            for (int j = 0; j < attributes.getLength(); j++) {
                attrib = attributes.item(j);
                String attribName = attrib.getNodeName();

                if (req.equals(attribName)) {
                    found = true;
                    break;
                }
            }

            if (!found) {
                return req;
            }

            // Go ahead and replace tokens in node values.
            tokenReplacer.replaceToken(attrib, getSourceFilename(attrib));

        }

        return null;
    }


    /**
     * Tests whether a configuration element's id is a valid
     * identifier. An id must be a String that is not null,
     * greater than 0 characters in length and not contain
     * any of the list delimiter characters, i.e. commas,
     * semi-colons or colons.
     *
     * @param id the Id String
     * @return boolean true if the id string is valid identification
     * @see ConfigurationConstants#LIST_DELIMITERS
     */
    public static boolean isValidID(String id) {
        if (id != null && id.length() > 0 && id.length() < 256) {
            char[] chars = id.toCharArray();
            for (int i = 0; i < chars.length; i++) {
                char c = chars[i];
                if (LIST_DELIMITERS.indexOf(c) != -1) {
                    return false;
                }
            }

            return true;
        }

        return false;
    }

    /**
     * Implement {@link org.xml.sax.EntityResolver#resolveEntity(String, String)}.
     * <p>
     * Flex Configuration does not need or use external entities, so disallow external entities
     * to prevent external entity injection attacks.
     *
     * @param publicId the public Id
     * @param systemId the system Id
     * @return InputSource the InputSource object
     * @throws SAXException when the parsing process failed with exceptions
     * @throws IOException  when the parsing process failed with exceptions
     */
    public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
        // Flex Configuration does not allow external entity defined by publicId {0} and SystemId {1}
        ConfigurationException ex = new ConfigurationException();
        ex.setMessage(EXTERNAL_ENTITY_NOT_ALLOW, new Object[]{publicId, systemId});
        throw ex;
    }
}
