/*
 * reserved comment block
 * DO NOT REMOVE OR ALTER!
 */
/*
 * Copyright 1999-2002,2004 The Apache Software Foundation.
 *
 * 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 com.sun.org.apache.xerces.internal.dom;

import org.w3c.dom.CharacterData;
import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

/**
 * Text nodes hold the non-markup, non-Entity content of
 * an Element or Attribute.
 * <P>
 * When a document is first made available to the DOM, there is only
 * one Text object for each block of adjacent plain-text. Users (ie,
 * applications) may create multiple adjacent Texts during editing --
 * see {@link org.w3c.dom.Element#normalize} for discussion.
 * <P>
 * Note that CDATASection is a subclass of Text. This is conceptually
 * valid, since they're really just two different ways of quoting
 * characters when they're written out as part of an XML stream.
 *
 * @xerces.internal
 *
 * @since  PR-DOM-Level-1-19980818.
 */
public class TextImpl
    extends CharacterDataImpl
    implements CharacterData, Text {

    //
    // Private Data members
    //


    //
    // Constants
    //

    /** Serialization version. */
    static final long serialVersionUID = -5294980852957403469L;

    //
    // Constructors
    //

    /** Default constructor */
    public TextImpl(){}

    /** Factory constructor. */
    public TextImpl(CoreDocumentImpl ownerDoc, String data) {
        super(ownerDoc, data);
    }

    /**
     * NON-DOM: resets node and sets specified values for the current node
     *
     * @param ownerDoc
     * @param data
     */
    public void setValues(CoreDocumentImpl ownerDoc, String data){

        flags=0;
        nextSibling = null;
        previousSibling=null;
        setOwnerDocument(ownerDoc);
        super.data = data;
    }
    //
    // Node methods
    //

    /**
     * A short integer indicating what type of node this is. The named
     * constants for this value are defined in the org.w3c.dom.Node interface.
     */
    public short getNodeType() {
        return Node.TEXT_NODE;
    }

    /** Returns the node name. */
    public String getNodeName() {
        return "#text";
    }

    /**
     * NON-DOM: Set whether this Text is ignorable whitespace.
     */
    public void setIgnorableWhitespace(boolean ignore) {

        if (needsSyncData()) {
            synchronizeData();
        }
        isIgnorableWhitespace(ignore);

    } // setIgnorableWhitespace(boolean)


    /**
     * DOM L3 Core CR - Experimental
     *
     * Returns whether this text node contains
     * element content whitespace</a>, often abusively called "ignorable whitespace".
     * The text node is determined to contain whitespace in element content
     * during the load of the document or if validation occurs while using
     * <code>Document.normalizeDocument()</code>.
     * @since DOM Level 3
     */
    public boolean isElementContentWhitespace() {
        // REVISIT: is this implemenation correct?
        if (needsSyncData()) {
            synchronizeData();
        }
        return internalIsIgnorableWhitespace();
    }


    /**
     * DOM Level 3 WD - Experimental.
     * Returns all text of <code>Text</code> nodes logically-adjacent text
     * nodes to this node, concatenated in document order.
     * @since DOM Level 3
     */
    public String getWholeText(){

        if (needsSyncData()) {
            synchronizeData();
        }

        if (fBufferStr == null){
            fBufferStr = new StringBuffer();
        }
        else {
            fBufferStr.setLength(0);
        }
        if (data != null && data.length() != 0) {
            fBufferStr.append(data);
        }

        //concatenate text of logically adjacent text nodes to the left of this node in the tree
        getWholeTextBackward(this.getPreviousSibling(), fBufferStr, this.getParentNode());
        String temp = fBufferStr.toString();

        //clear buffer
        fBufferStr.setLength(0);

        //concatenate text of logically adjacent text nodes to the right of this node in the tree
        getWholeTextForward(this.getNextSibling(), fBufferStr, this.getParentNode());

        return temp + fBufferStr.toString();

    }

    /**
     * internal method taking a StringBuffer in parameter and inserts the
     * text content at the start of the buffer
     *
     * @param buf
     */
    protected void insertTextContent(StringBuffer buf) throws DOMException {
         String content = getNodeValue();
         if (content != null) {
             buf.insert(0, content);
         }
     }

    /**
     * Concatenates the text of all logically-adjacent text nodes to the
     * right of this node
     * @param node
     * @param buffer
     * @param parent
     * @return true - if execution was stopped because the type of node
     *         other than EntityRef, Text, CDATA is encountered, otherwise
     *         return false
     */
    private boolean getWholeTextForward(Node node, StringBuffer buffer, Node parent){
        // boolean to indicate whether node is a child of an entity reference
        boolean inEntRef = false;

        if (parent!=null) {
                inEntRef = parent.getNodeType()==Node.ENTITY_REFERENCE_NODE;
        }

        while (node != null) {
            short type = node.getNodeType();
            if (type == Node.ENTITY_REFERENCE_NODE) {
                if (getWholeTextForward(node.getFirstChild(), buffer, node)){
                    return true;
                }
            }
            else if (type == Node.TEXT_NODE ||
                     type == Node.CDATA_SECTION_NODE) {
                ((NodeImpl)node).getTextContent(buffer);
            }
            else {
                return true;
            }

            node = node.getNextSibling();
        }

        // if the parent node is an entity reference node, must
        // check nodes to the right of the parent entity reference node for logically adjacent
        // text nodes
        if (inEntRef) {
            getWholeTextForward(parent.getNextSibling(), buffer, parent.getParentNode());
                        return true;
        }

        return false;
    }

    /**
     * Concatenates the text of all logically-adjacent text nodes to the left of
     * the node
     * @param node
     * @param buffer
     * @param parent
     * @return true - if execution was stopped because the type of node
     *         other than EntityRef, Text, CDATA is encountered, otherwise
     *         return false
     */
    private boolean getWholeTextBackward(Node node, StringBuffer buffer, Node parent){

        // boolean to indicate whether node is a child of an entity reference
        boolean inEntRef = false;
        if (parent!=null) {
                inEntRef = parent.getNodeType()==Node.ENTITY_REFERENCE_NODE;
        }

        while (node != null) {
            short type = node.getNodeType();
            if (type == Node.ENTITY_REFERENCE_NODE) {
                if (getWholeTextBackward(node.getLastChild(), buffer, node)){
                    return true;
                }
            }
            else if (type == Node.TEXT_NODE ||
                     type == Node.CDATA_SECTION_NODE) {
                ((TextImpl)node).insertTextContent(buffer);
            }
            else {
                return true;
            }

            node = node.getPreviousSibling();
        }

        // if the parent node is an entity reference node, must
        // check nodes to the left of the parent entity reference node for logically adjacent
        // text nodes
        if (inEntRef) {
                getWholeTextBackward(parent.getPreviousSibling(), buffer, parent.getParentNode());
            return true;
        }

        return false;
    }

    /**
     * Replaces the text of the current node and all logically-adjacent text
     * nodes with the specified text. All logically-adjacent text nodes are
     * removed including the current node unless it was the recipient of the
     * replacement text.
     *
     * @param content
     *            The content of the replacing Text node.
     * @return text - The Text node created with the specified content.
     * @since DOM Level 3
     */
    public Text replaceWholeText(String content) throws DOMException {

        if (needsSyncData()) {
            synchronizeData();
        }

        //if the content is null
        Node parent = this.getParentNode();
        if (content == null || content.length() == 0) {
            // remove current node
            if (parent != null) { // check if node in the tree
                parent.removeChild(this);
            }
            return null;
        }

        // make sure we can make the replacement
        if (ownerDocument().errorChecking) {
            if (!canModifyPrev(this)) {
                throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
                        DOMMessageFormatter.formatMessage(
                                DOMMessageFormatter.DOM_DOMAIN,
                                "NO_MODIFICATION_ALLOWED_ERR", null));
            }

            // make sure we can make the replacement
            if (!canModifyNext(this)) {
                throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
                        DOMMessageFormatter.formatMessage(
                                DOMMessageFormatter.DOM_DOMAIN,
                                "NO_MODIFICATION_ALLOWED_ERR", null));
            }
        }

        //replace the text node
        Text currentNode = null;
        if (isReadOnly()) {
            Text newNode = this.ownerDocument().createTextNode(content);
            if (parent != null) { // check if node in the tree
                parent.insertBefore(newNode, this);
                parent.removeChild(this);
                currentNode = newNode;
            } else {
                return newNode;
            }
        } else {
            this.setData(content);
            currentNode = this;
        }

        //check logically-adjacent text nodes
        Node prev = currentNode.getPreviousSibling();
        while (prev != null) {
            //If the logically-adjacent next node can be removed
            //remove it. A logically adjacent node can be removed if
            //it is a Text or CDATASection node or an EntityReference with
            //Text and CDATA only children.
            if ((prev.getNodeType() == Node.TEXT_NODE)
                    || (prev.getNodeType() == Node.CDATA_SECTION_NODE)
                    || (prev.getNodeType() == Node.ENTITY_REFERENCE_NODE && hasTextOnlyChildren(prev))) {
                parent.removeChild(prev);
                prev = currentNode;
            } else {
                break;
            }
            prev = prev.getPreviousSibling();
        }

        //check logically-adjacent text nodes
        Node next = currentNode.getNextSibling();
        while (next != null) {
            //If the logically-adjacent next node can be removed
            //remove it. A logically adjacent node can be removed if
            //it is a Text or CDATASection node or an EntityReference with
            //Text and CDATA only children.
            if ((next.getNodeType() == Node.TEXT_NODE)
                    || (next.getNodeType() == Node.CDATA_SECTION_NODE)
                    || (next.getNodeType() == Node.ENTITY_REFERENCE_NODE && hasTextOnlyChildren(next))) {
                parent.removeChild(next);
                next = currentNode;
            } else {
                break;
            }
            next = next.getNextSibling();
        }

        return currentNode;
    }

    /**
     * If any EntityReference to be removed has descendants that are not
     * EntityReference, Text, or CDATASection nodes, the replaceWholeText method
     * must fail before performing any modification of the document, raising a
     * DOMException with the code NO_MODIFICATION_ALLOWED_ERR. Traverse previous
     * siblings of the node to be replaced. If a previous sibling is an
     * EntityReference node, get it's last child. If the last child was a Text
     * or CDATASection node and its previous siblings are neither a replaceable
     * EntityReference or Text or CDATASection nodes, return false. IF the last
     * child was neither Text nor CDATASection nor a replaceable EntityReference
     * Node, then return true. If the last child was a Text or CDATASection node
     * any its previous sibling was not or was an EntityReference that did not
     * contain only Text or CDATASection nodes, return false. Check this
     * recursively for EntityReference nodes.
     *
     * @param node
     * @return true - can replace text false - can't replace exception must be
     *         raised
     */
    private boolean canModifyPrev(Node node) {
        boolean textLastChild = false;

        Node prev = node.getPreviousSibling();

        while (prev != null) {

            short type = prev.getNodeType();

            if (type == Node.ENTITY_REFERENCE_NODE) {
                //If the previous sibling was entityreference
                //check if its content is replaceable
                Node lastChild = prev.getLastChild();

                //if the entity reference has no children
                //return false
                if (lastChild == null) {
                    return false;
                }

                //The replacement text of the entity reference should
                //be either only text,cadatsections or replaceable entity
                //reference nodes or the last child should be neither of these
                while (lastChild != null) {
                    short lType = lastChild.getNodeType();

                    if (lType == Node.TEXT_NODE
                            || lType == Node.CDATA_SECTION_NODE) {
                        textLastChild = true;
                    } else if (lType == Node.ENTITY_REFERENCE_NODE) {
                        if (!canModifyPrev(lastChild)) {
                            return false;
                        } else {
                            //If the EntityReference child contains
                            //only text, or non-text or ends with a
                            //non-text node.
                            textLastChild = true;
                        }
                    } else {
                        //If the last child was replaceable and others are not
                        //Text or CDataSection or replaceable EntityRef nodes
                        //return false.
                        if (textLastChild) {
                            return false;
                        } else {
                            return true;
                        }
                    }
                    lastChild = lastChild.getPreviousSibling();
                }
            } else if (type == Node.TEXT_NODE
                    || type == Node.CDATA_SECTION_NODE) {
                //If the previous sibling was text or cdatasection move to next
            } else {
                //If the previous sibling was anything but text or
                //cdatasection or an entity reference, stop search and
                //return true
                return true;
            }

            prev = prev.getPreviousSibling();
        }

        return true;
    }

    /**
     * If any EntityReference to be removed has descendants that are not
     * EntityReference, Text, or CDATASection nodes, the replaceWholeText method
     * must fail before performing any modification of the document, raising a
     * DOMException with the code NO_MODIFICATION_ALLOWED_ERR. Traverse previous
     * siblings of the node to be replaced. If a previous sibling is an
     * EntityReference node, get it's last child. If the first child was a Text
     * or CDATASection node and its next siblings are neither a replaceable
     * EntityReference or Text or CDATASection nodes, return false. IF the first
     * child was neither Text nor CDATASection nor a replaceable EntityReference
     * Node, then return true. If the first child was a Text or CDATASection
     * node any its next sibling was not or was an EntityReference that did not
     * contain only Text or CDATASection nodes, return false. Check this
     * recursively for EntityReference nodes.
     *
     * @param node
     * @return true - can replace text false - can't replace exception must be
     *         raised
     */
    private boolean canModifyNext(Node node) {
        boolean textFirstChild = false;

        Node next = node.getNextSibling();
        while (next != null) {

            short type = next.getNodeType();

            if (type == Node.ENTITY_REFERENCE_NODE) {
                //If the previous sibling was entityreference
                //check if its content is replaceable
                Node firstChild = next.getFirstChild();

                //if the entity reference has no children
                //return false
                if (firstChild == null) {
                    return false;
                }

                //The replacement text of the entity reference should
                //be either only text,cadatsections or replaceable entity
                //reference nodes or the last child should be neither of these
                while (firstChild != null) {
                    short lType = firstChild.getNodeType();

                    if (lType == Node.TEXT_NODE
                            || lType == Node.CDATA_SECTION_NODE) {
                        textFirstChild = true;
                    } else if (lType == Node.ENTITY_REFERENCE_NODE) {
                        if (!canModifyNext(firstChild)) {
                            return false;
                        } else {
                            //If the EntityReference child contains
                            //only text, or non-text or ends with a
                            //non-text node.
                            textFirstChild = true;
                        }
                    } else {
                        //If the first child was replaceable text and next
                        //children are not, then return false
                        if (textFirstChild) {
                            return false;
                        } else {
                            return true;
                        }
                    }
                    firstChild = firstChild.getNextSibling();
                }
            } else if (type == Node.TEXT_NODE
                    || type == Node.CDATA_SECTION_NODE) {
                //If the previous sibling was text or cdatasection move to next
            } else {
                //If the next sibling was anything but text or
                //cdatasection or an entity reference, stop search and
                //return true
                return true;
            }

            next = next.getNextSibling();
        }

        return true;
    }

    /**
     * Check if an EntityReference node has Text Only child nodes
     *
     * @param node
     * @return true - Contains text only children
     */
    private boolean hasTextOnlyChildren(Node node) {

        Node child = node;

        if (child == null) {
            return false;
        }

        child = child.getFirstChild();
        while (child != null) {
            int type = child.getNodeType();

            if (type == Node.ENTITY_REFERENCE_NODE) {
                return hasTextOnlyChildren(child);
            }
            else if (type != Node.TEXT_NODE
                    && type != Node.CDATA_SECTION_NODE
                    && type != Node.ENTITY_REFERENCE_NODE) {
                return false;
            }
            child = child.getNextSibling();
        }
        return true;
    }


    /**
     * NON-DOM: Returns whether this Text is ignorable whitespace.
     */
    public boolean isIgnorableWhitespace() {

        if (needsSyncData()) {
            synchronizeData();
        }
        return internalIsIgnorableWhitespace();

    } // isIgnorableWhitespace():boolean


    //
    // Text methods
    //

    /**
     * Break a text node into two sibling nodes. (Note that if the current node
     * has no parent, they won't wind up as "siblings" -- they'll both be
     * orphans.)
     *
     * @param offset
     *            The offset at which to split. If offset is at the end of the
     *            available data, the second node will be empty.
     *
     * @return A reference to the new node (containing data after the offset
     *         point). The original node will contain data up to that point.
     *
     * @throws DOMException(INDEX_SIZE_ERR)
     *             if offset is <0 or >length.
     *
     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR)
     *             if node is read-only.
     */
    public Text splitText(int offset)
        throws DOMException {

        if (isReadOnly()) {
            throw new DOMException(
            DOMException.NO_MODIFICATION_ALLOWED_ERR,
                DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null));
        }

        if (needsSyncData()) {
            synchronizeData();
        }
        if (offset < 0 || offset > data.length() ) {
            throw new DOMException(DOMException.INDEX_SIZE_ERR,
                DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null));
        }

        // split text into two separate nodes
        Text newText =
            getOwnerDocument().createTextNode(data.substring(offset));
        setNodeValue(data.substring(0, offset));

        // insert new text node
        Node parentNode = getParentNode();
        if (parentNode != null) {
            parentNode.insertBefore(newText, nextSibling);
        }

        return newText;

    } // splitText(int):Text


    /**
     * NON-DOM (used by DOMParser): Reset data for the node.
     */
    public void replaceData (String value){
        data = value;
    }


    /**
     * NON-DOM (used by DOMParser: Sets data to empty string.
     *  Returns the value the data was set to.
     */
    public String removeData (){
        String olddata=data;
        data = "";
        return olddata;
    }

} // class TextImpl
