/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed 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.apache.harmony.xml.dom;

import java.util.Map;
import java.util.TreeMap;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMError;
import org.w3c.dom.DOMErrorHandler;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMStringList;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * A minimal implementation of DOMConfiguration. This implementation uses inner
 * parameter instances to centralize each parameter's behavior.
 */
public final class DOMConfigurationImpl implements DOMConfiguration {

    private static final Map<String, Parameter> PARAMETERS
            = new TreeMap<String, Parameter>(String.CASE_INSENSITIVE_ORDER);

    static {
        /*
         * True to canonicalize the document (unsupported). This includes
         * removing DocumentType nodes from the tree and removing unused
         * namespace declarations. Setting this to true also sets these
         * parameters:
         *   entities = false
         *   normalize-characters = false
         *   cdata-sections = false
         *   namespaces = true
         *   namespace-declarations = true
         *   well-formed = true
         *   element-content-whitespace = true
         * Setting these parameters to another value shall revert the canonical
         * form to false.
         */
        PARAMETERS.put("canonical-form", new FixedParameter(false));

        /*
         * True to keep existing CDATA nodes; false to replace them/merge them
         * into adjacent text nodes.
         */
        PARAMETERS.put("cdata-sections", new BooleanParameter() {
            public Object get(DOMConfigurationImpl config) {
                return config.cdataSections;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                config.cdataSections = (Boolean) value;
            }
        });

        /*
         * True to check character normalization (unsupported).
         */
        PARAMETERS.put("check-character-normalization", new FixedParameter(false));

        /*
         * True to keep comments in the document; false to discard them.
         */
        PARAMETERS.put("comments", new BooleanParameter() {
            public Object get(DOMConfigurationImpl config) {
                return config.comments;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                config.comments = (Boolean) value;
            }
        });

        /*
         * True to expose schema normalized values. Setting this to true sets
         * the validate parameter to true. Has no effect when validate is false.
         */
        PARAMETERS.put("datatype-normalization", new BooleanParameter() {
            public Object get(DOMConfigurationImpl config) {
                return config.datatypeNormalization;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                if ((Boolean) value) {
                    config.datatypeNormalization = true;
                    config.validate = true;
                } else {
                    config.datatypeNormalization = false;
                }
            }
        });

        /*
         * True to keep whitespace elements in the document; false to discard
         * them (unsupported).
         */
        PARAMETERS.put("element-content-whitespace", new FixedParameter(true));

        /*
         * True to keep entity references in the document; false to expand them.
         */
        PARAMETERS.put("entities", new BooleanParameter() {
            public Object get(DOMConfigurationImpl config) {
                return config.entities;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                config.entities = (Boolean) value;
            }
        });

        /*
         * Handler to be invoked when errors are encountered.
         */
        PARAMETERS.put("error-handler", new Parameter() {
            public Object get(DOMConfigurationImpl config) {
                return config.errorHandler;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                config.errorHandler = (DOMErrorHandler) value;
            }
            public boolean canSet(DOMConfigurationImpl config, Object value) {
                return value == null || value instanceof DOMErrorHandler;
            }
        });

        /*
         * Bulk alias to set the following parameter values:
         *   validate-if-schema = false
         *   entities = false
         *   datatype-normalization = false
         *   cdata-sections = false
         *   namespace-declarations = true
         *   well-formed = true
         *   element-content-whitespace = true
         *   comments = true
         *   namespaces = true.
         * Querying this returns true if all of the above parameters have the
         * listed values; false otherwise.
         */
        PARAMETERS.put("infoset", new BooleanParameter() {
            public Object get(DOMConfigurationImpl config) {
                // validate-if-schema is always false
                // element-content-whitespace is always true
                // namespace-declarations is always true
                return !config.entities
                        && !config.datatypeNormalization
                        && !config.cdataSections
                        && config.wellFormed
                        && config.comments
                        && config.namespaces;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                if ((Boolean) value) {
                    // validate-if-schema is always false
                    // element-content-whitespace is always true
                    // namespace-declarations is always true
                    config.entities = false;
                    config.datatypeNormalization = false;
                    config.cdataSections = false;
                    config.wellFormed = true;
                    config.comments = true;
                    config.namespaces = true;
                }
            }
        });

        /*
         * True to perform namespace processing; false for none.
         */
        PARAMETERS.put("namespaces", new BooleanParameter() {
            public Object get(DOMConfigurationImpl config) {
                return config.namespaces;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                config.namespaces = (Boolean) value;
            }
        });

        /**
         * True to include namespace declarations; false to discard them
         * (unsupported). Even when namespace declarations are discarded,
         * prefixes are retained.
         *
         * Has no effect if namespaces is false.
         */
        PARAMETERS.put("namespace-declarations", new FixedParameter(true));

        /*
         * True to fully normalize characters (unsupported).
         */
        PARAMETERS.put("normalize-characters", new FixedParameter(false));

        /*
         * A list of whitespace-separated URIs representing the schemas to validate
         * against. Has no effect if schema-type is null.
         */
        PARAMETERS.put("schema-location", new Parameter() {
            public Object get(DOMConfigurationImpl config) {
                return config.schemaLocation;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                config.schemaLocation = (String) value;
            }
            public boolean canSet(DOMConfigurationImpl config, Object value) {
                return value == null || value instanceof String;
            }
        });

        /*
         * URI representing the type of schema language, such as
         * "http://www.w3.org/2001/XMLSchema" or "http://www.w3.org/TR/REC-xml".
         */
        PARAMETERS.put("schema-type", new Parameter() {
            public Object get(DOMConfigurationImpl config) {
                return config.schemaType;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                config.schemaType = (String) value;
            }
            public boolean canSet(DOMConfigurationImpl config, Object value) {
                return value == null || value instanceof String;
            }
        });

        /*
         * True to split CDATA sections containing "]]>"; false to signal an
         * error instead.
         */
        PARAMETERS.put("split-cdata-sections", new BooleanParameter() {
            public Object get(DOMConfigurationImpl config) {
                return config.splitCdataSections;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                config.splitCdataSections = (Boolean) value;
            }
        });

        /*
         * True to require validation against a schema or DTD. Validation will
         * recompute element content whitespace, ID and schema type data.
         *
         * Setting this unsets validate-if-schema.
         */
        PARAMETERS.put("validate", new BooleanParameter() {
            public Object get(DOMConfigurationImpl config) {
                return config.validate;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                // validate-if-schema is always false
                config.validate = (Boolean) value;
            }
        });

        /*
         * True to validate if a schema was declared (unsupported). Setting this
         * unsets validate.
         */
        PARAMETERS.put("validate-if-schema", new FixedParameter(false));

        /*
         * True to report invalid characters in node names, attributes, elements,
         * comments, text, CDATA sections and processing instructions.
         */
        PARAMETERS.put("well-formed", new BooleanParameter() {
            public Object get(DOMConfigurationImpl config) {
                return config.wellFormed;
            }
            public void set(DOMConfigurationImpl config, Object value) {
                config.wellFormed = (Boolean) value;
            }
        });

        // TODO add "resource-resolver" property for use with LS feature...
    }

    private boolean cdataSections = true;
    private boolean comments = true;
    private boolean datatypeNormalization = false;
    private boolean entities = true;
    private DOMErrorHandler errorHandler;
    private boolean namespaces = true;
    private String schemaLocation;
    private String schemaType;
    private boolean splitCdataSections = true;
    private boolean validate = false;
    private boolean wellFormed = true;

    interface Parameter {
        Object get(DOMConfigurationImpl config);
        void set(DOMConfigurationImpl config, Object value);
        boolean canSet(DOMConfigurationImpl config, Object value);
    }

    static class FixedParameter implements Parameter {
        final Object onlyValue;
        FixedParameter(Object onlyValue) {
            this.onlyValue = onlyValue;
        }
        public Object get(DOMConfigurationImpl config) {
            return onlyValue;
        }
        public void set(DOMConfigurationImpl config, Object value) {
            if (!onlyValue.equals(value)) {
                throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
                        "Unsupported value: " + value);
            }
        }
        public boolean canSet(DOMConfigurationImpl config, Object value) {
            return onlyValue.equals(value);
        }
    }

    static abstract class BooleanParameter implements Parameter {
        public boolean canSet(DOMConfigurationImpl config, Object value) {
            return value instanceof Boolean;
        }
    }

    public boolean canSetParameter(String name, Object value) {
        Parameter parameter = PARAMETERS.get(name);
        return parameter != null && parameter.canSet(this, value);
    }

    public void setParameter(String name, Object value) throws DOMException {
        Parameter parameter = PARAMETERS.get(name);
        if (parameter == null) {
            throw new DOMException(DOMException.NOT_FOUND_ERR, "No such parameter: " + name);
        }
        try {
            parameter.set(this, value);
        } catch (NullPointerException e) {
            throw new DOMException(DOMException.TYPE_MISMATCH_ERR,
                    "Null not allowed for " + name);
        } catch (ClassCastException e) {
            throw new DOMException(DOMException.TYPE_MISMATCH_ERR,
                    "Invalid type for " + name + ": " + value.getClass());
        }
    }

    public Object getParameter(String name) throws DOMException {
        Parameter parameter = PARAMETERS.get(name);
        if (parameter == null) {
            throw new DOMException(DOMException.NOT_FOUND_ERR, "No such parameter: " + name);
        }
        return parameter.get(this);
    }

    public DOMStringList getParameterNames() {
        return internalGetParameterNames();
    }

    private static DOMStringList internalGetParameterNames() {
        final String[] result = PARAMETERS.keySet().toArray(new String[PARAMETERS.size()]);
        return new DOMStringList() {
            public String item(int index) {
                return index < result.length ? result[index] : null;
            }
            public int getLength() {
                return result.length;
            }
            public boolean contains(String str) {
                return PARAMETERS.containsKey(str); // case-insensitive.
            }
        };
    }

    public void normalize(Node node) {
        /*
         * Since we don't validate, this code doesn't take into account the
         * following "supported" parameters: datatype-normalization, entities,
         * schema-location, schema-type, or validate.
         *
         * TODO: normalize namespaces
         */

        switch (node.getNodeType()) {
            case Node.CDATA_SECTION_NODE:
                CDATASectionImpl cdata = (CDATASectionImpl) node;
                if (cdataSections) {
                    if (cdata.needsSplitting()) {
                        if (splitCdataSections) {
                            cdata.split();
                            report(DOMError.SEVERITY_WARNING, "cdata-sections-splitted");
                        } else {
                            report(DOMError.SEVERITY_ERROR, "wf-invalid-character");
                        }
                    }
                    checkTextValidity(cdata.buffer);
                    break;
                }
                node = cdata.replaceWithText();
                // fall through

            case Node.TEXT_NODE:
                TextImpl text = (TextImpl) node;
                text = text.minimize();
                if (text != null) {
                    checkTextValidity(text.buffer);
                }
                break;

            case Node.COMMENT_NODE:
                CommentImpl comment = (CommentImpl) node;
                if (!comments) {
                    comment.getParentNode().removeChild(comment);
                    break;
                }
                if (comment.containsDashDash()) {
                    report(DOMError.SEVERITY_ERROR, "wf-invalid-character");
                }
                checkTextValidity(comment.buffer);
                break;

            case Node.PROCESSING_INSTRUCTION_NODE:
                checkTextValidity(((ProcessingInstructionImpl) node).getData());
                break;

            case Node.ATTRIBUTE_NODE:
                checkTextValidity(((AttrImpl) node).getValue());
                break;

            case Node.ELEMENT_NODE:
                ElementImpl element = (ElementImpl) node;
                NamedNodeMap attributes = element.getAttributes();
                for (int i = 0; i < attributes.getLength(); i++) {
                    normalize(attributes.item(i));
                }
                // fall through

            case Node.DOCUMENT_NODE:
            case Node.DOCUMENT_FRAGMENT_NODE:
                Node next;
                for (Node child = node.getFirstChild(); child != null; child = next) {
                    // lookup next eagerly because normalize() may remove its subject
                    next = child.getNextSibling();
                    normalize(child);
                }
                break;

            case Node.NOTATION_NODE:
            case Node.DOCUMENT_TYPE_NODE:
            case Node.ENTITY_NODE:
            case Node.ENTITY_REFERENCE_NODE:
                break;

            default:
                throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
                        "Unsupported node type " + node.getNodeType());
        }
    }

    private void checkTextValidity(CharSequence s) {
        if (wellFormed && !isValid(s)) {
            report(DOMError.SEVERITY_ERROR, "wf-invalid-character");
        }
    }

    /**
     * Returns true if all of the characters in the text are permitted for use
     * in XML documents.
     */
    private boolean isValid(CharSequence text) {
        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            // as defined by http://www.w3.org/TR/REC-xml/#charsets.
            boolean valid = c == 0x9 || c == 0xA || c == 0xD
                    || (c >= 0x20 && c <= 0xd7ff)
                    || (c >= 0xe000 && c <= 0xfffd);
            if (!valid) {
                return false;
            }
        }
        return true;
    }

    private void report(short severity, String type) {
        if (errorHandler != null) {
            // TODO: abort if handleError returns false
            errorHandler.handleError(new DOMErrorImpl(severity, type));
        }
    }
}
