FileDocCategorySizeDatePackage
TextImpl.javaAPI DocApache Xerces 3.0.123818Fri Sep 14 20:33:52 BST 2007org.apache.xerces.dom

TextImpl

public class TextImpl extends CharacterDataImpl implements CharacterData, Text
Text nodes hold the non-markup, non-Entity content of an Element or Attribute.

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.

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
version
$Id: TextImpl.java 447266 2006-09-18 05:57:49Z mrglavas $
since
PR-DOM-Level-1-19980818.

Fields Summary
static final long
serialVersionUID
Serialization version.
Constructors Summary
public TextImpl()
Default constructor

        
    //
    // Constructors
    //

       
     
public TextImpl(CoreDocumentImpl ownerDoc, String data)
Factory constructor.

        super(ownerDoc, data);
    
Methods Summary
private booleancanModifyNext(org.w3c.dom.Node node)
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

        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;
    
private booleancanModifyPrev(org.w3c.dom.Node node)
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

        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;
    
public java.lang.StringgetNodeName()
Returns the node name.

        return "#text";
    
public shortgetNodeType()
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.

        return Node.TEXT_NODE;
    
public java.lang.StringgetWholeText()
DOM Level 3 WD - Experimental. Returns all text of Text nodes logically-adjacent text nodes to this node, concatenated in document order.

since
DOM Level 3

        
        if (needsSyncData()) {
            synchronizeData();
        }
     
        StringBuffer buffer = new StringBuffer();
        if (data != null && data.length() != 0) {
            buffer.append(data);
        }
        
        // concatenate text of logically adjacent text nodes to the left of this node in the tree
        getWholeTextBackward(this.getPreviousSibling(), buffer, this.getParentNode());
        String temp = buffer.toString();
      
        // clear buffer
        buffer.setLength(0);
        
        // concatenate text of logically adjacent text nodes to the right of this node in the tree
        getWholeTextForward(this.getNextSibling(), buffer, this.getParentNode());
        
        return temp + buffer.toString();
        
    
private booleangetWholeTextBackward(org.w3c.dom.Node node, java.lang.StringBuffer buffer, org.w3c.dom.Node parent)
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

    	
    	// 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;
    
private booleangetWholeTextForward(org.w3c.dom.Node node, java.lang.StringBuffer buffer, org.w3c.dom.Node parent)
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

    	// 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;
    
private booleanhasTextOnlyChildren(org.w3c.dom.Node node)
Check if an EntityReference node has Text Only child nodes

param
node
return
true - Contains text only children


        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;
    
protected voidinsertTextContent(java.lang.StringBuffer buf)
internal method taking a StringBuffer in parameter and inserts the text content at the start of the buffer

param
buf

         String content = getNodeValue();
         if (content != null) {
             buf.insert(0, content);
         }
     
public booleanisElementContentWhitespace()
DOM L3 Core CR - Experimental Returns whether this text node contains element content whitespace, 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 Document.normalizeDocument().

since
DOM Level 3

        // REVISIT: is this implemenation correct?
        if (needsSyncData()) {
            synchronizeData();
        }
        return internalIsIgnorableWhitespace();
    
public booleanisIgnorableWhitespace()
NON-DOM: Returns whether this Text is ignorable whitespace.


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

    
public java.lang.StringremoveData()
NON-DOM (used by DOMParser: Sets data to empty string. Returns the value the data was set to.

        String olddata=data;
        data = "";
        return olddata;
    
public voidreplaceData(java.lang.String value)
NON-DOM (used by DOMParser): Reset data for the node.

        data = value;
    
public org.w3c.dom.TextreplaceWholeText(java.lang.String content)
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


        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;
    
public voidsetIgnorableWhitespace(boolean ignore)
NON-DOM: Set whether this Text is ignorable whitespace.


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

    
public voidsetValues(CoreDocumentImpl ownerDoc, java.lang.String data)
NON-DOM: resets node and sets specified values for the current node

param
ownerDoc
param
data


        flags=0;
        nextSibling = null;
        previousSibling=null;
        setOwnerDocument(ownerDoc);
        super.data = data;
    
public org.w3c.dom.TextsplitText(int offset)
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.


        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;