- /*
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Xerces" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
- * Business Machines, Inc., http://www.apache.org. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
- package com.sun.org.apache.xerces.internal.dom;
-
- import org.w3c.dom.DOMException;
- import org.w3c.dom.Node;
- import org.w3c.dom.NodeList;
-
- /**
- * CharacterData is an abstract Node that can carry character data as its
- * Value. It provides shared behavior for Text, CData, and
- * possibly other node types. All offsets are 0-based.
- * <p>
- * Since ProcessingInstructionImpl inherits from this class to reuse the
- * setNodeValue method, this class isn't declared as implementing the interface
- * CharacterData. This is done by relevant subclasses (TexImpl, CommentImpl).
- * <p>
- * This class doesn't directly support mutation events, however, it notifies
- * the document when mutations are performed so that the document class do so.
- *
- * @version $Id: CharacterDataImpl.java,v 1.20 2003/05/08 19:52:40 elena Exp $
- * @since PR-DOM-Level-1-19980818.
- */
- public abstract class CharacterDataImpl
- extends ChildNode {
-
- //
- // Constants
- //
-
- /** Serialization version. */
- static final long serialVersionUID = 7931170150428474230L;
-
- //
- // Data
- //
-
- protected String data;
-
- /** Empty child nodes. */
- private static transient NodeList singletonNodeList = new NodeList() {
- public Node item(int index) { return null; }
- public int getLength() { return 0; }
- };
-
- //
- // Constructors
- //
-
- public CharacterDataImpl(){}
-
- /** Factory constructor. */
- protected CharacterDataImpl(CoreDocumentImpl ownerDocument, String data) {
- super(ownerDocument);
- this.data = data;
- }
-
- //
- // Node methods
- //
-
- /** Returns an empty node list. */
- public NodeList getChildNodes() {
- return singletonNodeList;
- }
-
- /*
- * returns the content of this node
- */
- public String getNodeValue() {
- if (needsSyncData()) {
- synchronizeData();
- }
- return data;
- }
-
- /** This function added so that we can distinguish whether
- * setNodeValue has been called from some other DOM functions.
- * or by the client.<p>
- * This is important, because we do one type of Range fix-up,
- * from the high-level functions in CharacterData, and another
- * type if the client simply calls setNodeValue(value).
- */
- protected void setNodeValueInternal(String value) {
- if (isReadOnly()) {
- String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
- throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
- }
- // revisit: may want to set the value in ownerDocument.
- // Default behavior, overridden in some subclasses
- if (needsSyncData()) {
- synchronizeData();
- }
-
- // keep old value for document notification
- String oldvalue = this.data;
-
- CoreDocumentImpl ownerDocument = ownerDocument();
-
- // notify document
- ownerDocument.modifyingCharacterData(this);
-
- this.data = value;
-
- // notify document
- ownerDocument.modifiedCharacterData(this, oldvalue, value);
- }
-
- /**
- * Sets the content, possibly firing related events,
- * and updating ranges (via notification to the document)
- */
- public void setNodeValue(String value) {
-
- setNodeValueInternal(value);
-
- // notify document
- ownerDocument().replacedText(this);
- }
-
- //
- // CharacterData methods
- //
-
- /**
- * Retrieve character data currently stored in this node.
- *
- * @throws DOMExcpetion(DOMSTRING_SIZE_ERR) In some implementations,
- * the stored data may exceed the permitted length of strings. If so,
- * getData() will throw this DOMException advising the user to
- * instead retrieve the data in chunks via the substring() operation.
- */
- public String getData() {
- if (needsSyncData()) {
- synchronizeData();
- }
- return data;
- }
-
- /**
- * Report number of characters currently stored in this node's
- * data. It may be 0, meaning that the value is an empty string.
- */
- public int getLength() {
- if (needsSyncData()) {
- synchronizeData();
- }
- return data.length();
- }
-
- /**
- * Concatenate additional characters onto the end of the data
- * stored in this node. Note that this, and insert(), are the paths
- * by which a DOM could wind up accumulating more data than the
- * language's strings can easily handle. (See above discussion.)
- *
- * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
- */
- public void appendData(String data) {
-
- if (isReadOnly()) {
- String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
- throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
- }
- if (data == null) {
- return;
- }
- if (needsSyncData()) {
- synchronizeData();
- }
-
- setNodeValue(this.data + data);
-
- } // appendData(String)
-
- /**
- * Remove a range of characters from the node's value. Throws a
- * DOMException if the offset is beyond the end of the
- * string. However, a deletion _count_ that exceeds the available
- * data is accepted as a delete-to-end request.
- *
- * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
- * greater than length, or if count is negative.
- *
- * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is
- * readonly.
- */
- public void deleteData(int offset, int count)
- throws DOMException {
-
- if (isReadOnly()) {
- String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
- throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
- }
-
- if (count < 0) {
- String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
- throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
- }
-
- if (needsSyncData()) {
- synchronizeData();
- }
- int tailLength = Math.max(data.length() - count - offset, 0);
- try {
- String value = data.substring(0, offset) +
- (tailLength > 0
- ? data.substring(offset + count, offset + count + tailLength)
- : "");
-
- setNodeValueInternal(value);
-
- // notify document
- ownerDocument().deletedText(this, offset, count);
- }
- catch (StringIndexOutOfBoundsException e) {
- String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
- throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
- }
-
- } // deleteData(int,int)
-
- /**
- * Insert additional characters into the data stored in this node,
- * at the offset specified.
- *
- * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
- * greater than length.
- *
- * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
- */
- public void insertData(int offset, String data)
- throws DOMException {
-
- if (isReadOnly()) {
- String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
- throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
- }
-
- if (needsSyncData()) {
- synchronizeData();
- }
- try {
- String value =
- new StringBuffer(this.data).insert(offset, data).toString();
-
- setNodeValueInternal(value);
-
- // notify document
- ownerDocument().insertedText(this, offset, data.length());
- }
- catch (StringIndexOutOfBoundsException e) {
- String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
- throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
- }
-
- } // insertData(int,int)
-
- /**
- * Replace a series of characters at the specified (zero-based)
- * offset with a new string, NOT necessarily of the same
- * length. Convenience method, equivalent to a delete followed by an
- * insert. Throws a DOMException if the specified offset is beyond
- * the end of the existing data.
- *
- * @param offset The offset at which to begin replacing.
- *
- * @param count The number of characters to remove,
- * interpreted as in the delete() method.
- *
- * @param data The new string to be inserted at offset in place of
- * the removed data. Note that the entire string will
- * be inserted -- the count parameter does not affect
- * insertion, and the new data may be longer or shorter
- * than the substring it replaces.
- *
- * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
- * greater than length, or if count is negative.
- *
- * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is
- * readonly.
- */
- public void replaceData(int offset, int count, String data)
- throws DOMException {
-
- // The read-only check is done by deleteData()
- // ***** This could be more efficient w/r/t Mutation Events,
- // specifically by aggregating DOMAttrModified and
- // DOMSubtreeModified. But mutation events are
- // underspecified; I don't feel compelled
- // to deal with it right now.
- deleteData(offset, count);
- insertData(offset, data);
-
- } // replaceData(int,int,String)
-
- /**
- * Store character data into this node.
- *
- * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
- */
- public void setData(String value)
- throws DOMException {
- setNodeValue(value);
- }
-
- /**
- * Substring is more than a convenience function. In some
- * implementations of the DOM, where the stored data may exceed the
- * length that can be returned in a single string, the only way to
- * read it all is to extract it in chunks via this method.
- *
- * @param offset Zero-based offset of first character to retrieve.
- * @param count Number of characters to retrieve.
- *
- * If the sum of offset and count exceeds the length, all characters
- * to end of data are returned.
- *
- * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
- * greater than length, or if count is negative.
- *
- * @throws DOMException(WSTRING_SIZE_ERR) In some implementations,
- * count may exceed the permitted length of strings. If so,
- * substring() will throw this DOMException advising the user to
- * instead retrieve the data in smaller chunks.
- */
- public String substringData(int offset, int count)
- throws DOMException {
-
- if (needsSyncData()) {
- synchronizeData();
- }
-
- int length = data.length();
- if (count < 0 || offset < 0 || offset > length - 1) {
- String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
- throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
- }
-
- int tailIndex = Math.min(offset + count, length);
-
- return data.substring(offset, tailIndex);
-
- } // substringData(int,int):String
-
- } // class CharacterDataImpl