/*
* Copyright 1999-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.
*
* CVS $Id: CharacterDataImpl.java,v 1.11 2004/02/08 03:11:56 vgritsenko Exp $
*/
package org.apache.xindice.xml.dom;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xindice.util.ByteArrayInput;
import org.apache.xindice.xml.SymbolTable;
import org.apache.xindice.xml.XMLCompressedInput;
import org.w3c.dom.CharacterData;
import org.w3c.dom.DOMException;
/**
* CharacterDataImpl
*
* @version CVS $Revision: 1.11 $, $Date: 2004/02/08 03:11:56 $
*/
public abstract class CharacterDataImpl extends NodeImpl implements CharacterData {
private static final Log log = LogFactory.getLog(CharacterDataImpl.class);
public CharacterDataImpl() {
}
public CharacterDataImpl(NodeImpl parentNode, byte[] data, int pos, int len) {
super(parentNode, data, pos, len);
}
public CharacterDataImpl(NodeImpl parentNode, boolean dirty) {
super(parentNode, dirty);
}
public CharacterDataImpl(NodeImpl parentNode, String nodeValue) {
super(parentNode, true);
if (nodeValue == null) {
nodeValue = "";
}
this.nodeValue = nodeValue;
}
protected final void checkLoaded() {
if (loaded) {
return;
} else {
loaded = true;
}
try {
if (data != null) {
DocumentImpl doc = (DocumentImpl) getOwnerDocument();
SymbolTable st = doc.getSymbols();
ByteArrayInput bis = new ByteArrayInput(data, pos, len);
XMLCompressedInput xci = new XMLCompressedInput(bis, st);
xci.readSignature(); // Skip The Signature
if (getNodeType() == TEXT_NODE) {
xci.readContentSize();
} else {
xci.readInt();
}
byte[] buf = new byte[bis.available()];
xci.read(buf);
nodeValue = new String(buf, "UTF-8");
}
} catch (Exception e) {
if (log.isWarnEnabled()) {
log.warn("ignored exception", e);
}
}
}
public final void setNodeValue(String nodeValue) throws DOMException {
checkLoaded();
checkReadOnly();
if (nodeValue == null) {
nodeValue = "";
}
this.nodeValue = nodeValue;
setDirty();
}
/**
* Extracts a range of data from the node.
* @param offset Start offset of substring to extract.
* @param count The number of characters to extract.
* @return The specified substring. If the sum of <code>offset</code> and
* <code>count</code> exceeds the <code>length</code>, then all
* characters to the end of the data are returned.
* @exception DOMException
* INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
* than the number of characters 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 final String substringData(int offset, int count) throws DOMException {
try {
return nodeValue.substring(offset, offset + count);
} catch (Exception e) {
throw EX_INDEX_SIZE;
}
}
/**
* 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 final String getData() throws DOMException {
return getNodeValue();
}
public final void setData(String data) throws DOMException {
setNodeValue(data);
}
/**
* Insert a string at the specified character 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 offset is negative or greater
* than the number of characters in <code>data</code>.
* <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
*/
public final void insertData(int offset, String arg) throws DOMException {
String value = getNodeValue();
checkReadOnly();
try {
setNodeValue(value.substring(0, offset) + arg + value.substring(offset + 1));
} catch (Exception e) {
throw EX_INDEX_SIZE;
}
}
/**
* The number of characters 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 final int getLength() {
return getNodeValue().length();
}
/**
* Replace the characters starting at the specified character offset with
* the specified string.
* @param offset The offset from which to start replacing.
* @param count The number of characters to replace. If the sum of
* <code>offset</code> and <code>count</code> exceeds <code>length</code>
* , then all characters 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 offset is negative or greater
* than the number of characters 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 final void replaceData(int offset, int count, String arg) throws DOMException {
String value = getNodeValue();
checkReadOnly();
try {
setNodeValue(value.substring(0, offset) + arg + value.substring(offset + count));
} catch (Exception e) {
throw EX_INDEX_SIZE;
}
}
/**
* 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 final void appendData(String arg) throws DOMException {
String value = getNodeValue();
checkReadOnly();
setNodeValue(value + arg);
}
/**
* Remove a range of characters from the node. Upon success,
* <code>data</code> and <code>length</code> reflect the change.
* @param offset The offset from which to remove characters.
* @param count The number of characters to delete. If the sum of
* <code>offset</code> and <code>count</code> exceeds <code>length</code>
* then all characters from <code>offset</code> to the end of the data
* are deleted.
* @exception DOMException
* INDEX_SIZE_ERR: Raised if the specified offset is negative or greater
* than the number of characters 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 final void deleteData(int offset, int count) throws DOMException {
String value = getNodeValue();
checkReadOnly();
try {
setNodeValue(value.substring(0, offset) + value.substring(offset + count));
} catch (Exception e) {
throw EX_INDEX_SIZE;
}
}
}