/*
* Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package com.sun.ukit.dom;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.DOMException;
/**
* DOM character data node implementation.
*
* @see org.w3c.dom.Node
*/
public abstract class XCharData
extends XNode
implements CharacterData
{
/** Empty node list */
private final static NodeList empty = new XList();
/** Character data. */
private String chdat;
/**
* Constructs element object from other element.
*/
protected XCharData(XCharData node, boolean deep)
{
super(node, deep);
chdat = node.chdat;
}
/**
* Constructs character data object from node name and its owner document.
*/
protected XCharData(String nodename, XDoc ownerDocument, String data)
{
super(null, nodename, ownerDocument);
chdat = data;
}
/**
* A code representing the type of the underlying object, as defined above.
*/
public abstract short getNodeType();
/**
* The value of this node, depending on its type.
* When it is defined to be <code>null</code>, setting it has no effect.
*
* @exception DOMException
* NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
* @exception DOMException
* DOMSTRING_SIZE_ERR: Raised when it would return more characters than
* fit in a <code>DOMString</code> variable on the implementation
* platform.
*/
public String getNodeValue()
throws DOMException
{
return getData();
}
/**
* The value of this node, depending on its type.
* When it is defined to be <code>null</code>, setting it has no effect.
*
* @exception DOMException
* NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
* @exception DOMException
* DOMSTRING_SIZE_ERR: Raised when it would return more characters than
* fit in a <code>DOMString</code> variable on the implementation
* platform.
*/
public void setNodeValue(String nodeValue)
throws DOMException
{
setData(nodeValue);
}
/**
* A <code>NodeList</code> that contains all children of this node. If
* there are no children, this is a <code>NodeList</code> containing no
* nodes.
*/
public NodeList getChildNodes()
{
return empty;
}
/**
* The character data of the node that implements this interface. The DOM
* implementation may not put arbitrary limits on the amount of data
* that may be stored in a <code>CharacterData</code> node. However,
* implementation limits may mean that the entirety of a node's data may
* not fit into a single <code>DOMString</code>. In such cases, the user
* may call <code>substringData</code> to retrieve the data in
* appropriately sized pieces.
*
* @exception DOMException
* DOMSTRING_SIZE_ERR: Raised when it would return more characters than
* fit in a <code>DOMString</code> variable on the implementation
* platform.
*/
public String getData()
throws DOMException
{
return chdat;
}
/**
* The character data of the node that implements this interface. The DOM
* implementation may not put arbitrary limits on the amount of data
* that may be stored in a <code>CharacterData</code> node. However,
* implementation limits may mean that the entirety of a node's data may
* not fit into a single <code>DOMString</code>. In such cases, the user
* may call <code>substringData</code> to retrieve the data in
* appropriately sized pieces.
*
* @exception DOMException
* NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
* @exception DOMException
* DOMSTRING_SIZE_ERR: Raised when it would return more characters than
* fit in a <code>DOMString</code> variable on the implementation
* platform.
*/
public void setData(String data)
throws DOMException
{
if (_isRO())
throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "");
String olddat = chdat;
chdat = (data != null)? data: "";
_dataChanged(olddat, chdat);
}
/**
* The number of 16-bit units that are available through <code>data</code>
* and the <code>substringData</code> method below. This may have the
* value zero, i.e., <code>CharacterData</code> nodes may be empty.
*/
public int getLength()
{
return chdat.length();
}
/**
* Extracts a range of data from the node.
*
* @param offset Start offset of substring to extract.
* @param count The number of 16-bit units to extract.
* @return The specified substring. If the sum of <code>offset</code> and
* <code>count</code> exceeds the <code>length</code>, then all 16-bit
* units to the end of the data are returned.
* @exception DOMException
* INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is
* negative or greater than the number of 16-bit units in
* <code>data</code>, or if the specified <code>count</code> is
* negative.
* <br>DOMSTRING_SIZE_ERR: Raised if the specified range of text does
* not fit into a <code>DOMString</code>.
*/
public String substringData(int offset, int count)
throws DOMException
{
try {
int tail = offset + count;
if (tail > chdat.length())
tail = chdat.length();
return chdat.substring(offset, tail);
} catch (IndexOutOfBoundsException iob) {
throw new DOMException(DOMException.INDEX_SIZE_ERR, "");
}
}
/**
* Append the string to the end of the character data of the node. Upon
* success, <code>data</code> provides access to the concatenation of
* <code>data</code> and the <code>DOMString</code> specified.
*
* @param arg The <code>DOMString</code> to append.
* @exception DOMException
* NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
*/
public void appendData(String arg)
throws DOMException
{
if (_isRO())
throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "");
String olddat = chdat;
if (arg != null && arg.length() > 0)
chdat = chdat.concat(arg);
_dataChanged(olddat, chdat);
}
/**
* Insert a string at the specified 16-bit unit offset.
*
* @param offset The character offset at which to insert.
* @param arg The <code>DOMString</code> to insert.
* @exception DOMException
* INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is
* negative or greater than the number of 16-bit units in
* <code>data</code>.
* <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
*/
public void insertData(int offset, String arg)
throws DOMException
{
if (_isRO())
throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "");
String olddat = chdat;
try {
String head = chdat.substring(0, offset);
chdat = head + arg + chdat.substring(offset);
} catch (IndexOutOfBoundsException iob) {
throw new DOMException(DOMException.INDEX_SIZE_ERR, "");
}
_dataChanged(olddat, chdat);
}
/**
* Remove a range of 16-bit units from the node. Upon success,
* <code>data</code> and <code>length</code> reflect the change.
*
* @param offset The offset from which to start removing.
* @param count The number of 16-bit units to delete. If the sum of
* <code>offset</code> and <code>count</code> exceeds
* <code>length</code> then all 16-bit units from <code>offset</code>
* to the end of the data are deleted.
* @exception DOMException
* INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is
* negative or greater than the number of 16-bit units in
* <code>data</code>, or if the specified <code>count</code> is
* negative.
* <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
*/
public void deleteData(int offset, int count)
throws DOMException
{
if (_isRO())
throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "");
if (offset < 0 || count < 0 || offset > chdat.length())
throw new DOMException(DOMException.INDEX_SIZE_ERR, "");
String olddat = chdat;
try {
String head = chdat.substring(0, offset);
if ((offset + count) < chdat.length())
chdat = head + chdat.substring(offset + count);
else
chdat = head;
} catch (IndexOutOfBoundsException iob) {
throw new DOMException(DOMException.INDEX_SIZE_ERR, "");
}
_dataChanged(olddat, chdat);
}
/**
* Replace the characters starting at the specified 16-bit unit offset
* with the specified string.
*
* @param offset The offset from which to start replacing.
* @param count The number of 16-bit units to replace. If the sum of
* <code>offset</code> and <code>count</code> exceeds
* <code>length</code>, then all 16-bit units to the end of the data
* are replaced; (i.e., the effect is the same as a <code>remove</code>
* method call with the same range, followed by an <code>append</code>
* method invocation).
* @param arg The <code>DOMString</code> with which the range must be
* replaced.
* @exception DOMException
* INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is
* negative or greater than the number of 16-bit units in
* <code>data</code>, or if the specified <code>count</code> is
* negative.
* <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
*/
public void replaceData(int offset, int count, String arg)
throws DOMException
{
if (_isRO())
throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "");
if (offset < 0 || count < 0 || offset > chdat.length())
throw new DOMException(DOMException.INDEX_SIZE_ERR, "");
String olddat = chdat;
try {
String head = chdat.substring(0, offset);
int num = (offset + count <= chdat.length())?
count: chdat.length() - offset;
chdat = head + arg + chdat.substring(offset + num);
} catch (IndexOutOfBoundsException iob) {
throw new DOMException(DOMException.INDEX_SIZE_ERR, "");
}
_dataChanged(olddat, chdat);
}
/**
* Notification of data change.
*/
protected void _dataChanged(String oldData, String newData)
{
super._dataChanged(oldData, newData);
XNode attr = (XNode)_getParent();
if (attr != null && attr.getNodeType() == ATTRIBUTE_NODE)
attr._updateValue(attr.getTextContent());
}
}