KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > dom > CharacterDataImpl


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package com.sun.org.apache.xerces.internal.dom;
59
60 import org.w3c.dom.DOMException JavaDoc;
61 import org.w3c.dom.Node JavaDoc;
62 import org.w3c.dom.NodeList JavaDoc;
63
64 /**
65  * CharacterData is an abstract Node that can carry character data as its
66  * Value. It provides shared behavior for Text, CData, and
67  * possibly other node types. All offsets are 0-based.
68  * <p>
69  * Since ProcessingInstructionImpl inherits from this class to reuse the
70  * setNodeValue method, this class isn't declared as implementing the interface
71  * CharacterData. This is done by relevant subclasses (TexImpl, CommentImpl).
72  * <p>
73  * This class doesn't directly support mutation events, however, it notifies
74  * the document when mutations are performed so that the document class do so.
75  *
76  * @version $Id: CharacterDataImpl.java,v 1.20 2003/05/08 19:52:40 elena Exp $
77  * @since PR-DOM-Level-1-19980818.
78  */

79 public abstract class CharacterDataImpl
80     extends ChildNode {
81
82     //
83
// Constants
84
//
85

86     /** Serialization version. */
87     static final long serialVersionUID = 7931170150428474230L;
88
89     //
90
// Data
91
//
92

93     protected String JavaDoc data;
94
95     /** Empty child nodes. */
96     private static transient NodeList JavaDoc singletonNodeList = new NodeList JavaDoc() {
97         public Node JavaDoc item(int index) { return null; }
98         public int getLength() { return 0; }
99     };
100
101     //
102
// Constructors
103
//
104

105     public CharacterDataImpl(){}
106
107     /** Factory constructor. */
108     protected CharacterDataImpl(CoreDocumentImpl ownerDocument, String JavaDoc data) {
109         super(ownerDocument);
110         this.data = data;
111     }
112
113     //
114
// Node methods
115
//
116

117     /** Returns an empty node list. */
118     public NodeList JavaDoc getChildNodes() {
119         return singletonNodeList;
120     }
121
122     /*
123      * returns the content of this node
124      */

125     public String JavaDoc getNodeValue() {
126         if (needsSyncData()) {
127             synchronizeData();
128         }
129         return data;
130     }
131
132     /** This function added so that we can distinguish whether
133      * setNodeValue has been called from some other DOM functions.
134      * or by the client.<p>
135      * This is important, because we do one type of Range fix-up,
136      * from the high-level functions in CharacterData, and another
137      * type if the client simply calls setNodeValue(value).
138      */

139     protected void setNodeValueInternal(String JavaDoc value) {
140         if (isReadOnly()) {
141             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
142             throw new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
143         }
144         // revisit: may want to set the value in ownerDocument.
145
// Default behavior, overridden in some subclasses
146
if (needsSyncData()) {
147             synchronizeData();
148         }
149
150         // keep old value for document notification
151
String JavaDoc oldvalue = this.data;
152
153         CoreDocumentImpl ownerDocument = ownerDocument();
154
155         // notify document
156
ownerDocument.modifyingCharacterData(this);
157
158         this.data = value;
159
160         // notify document
161
ownerDocument.modifiedCharacterData(this, oldvalue, value);
162     }
163
164     /**
165      * Sets the content, possibly firing related events,
166      * and updating ranges (via notification to the document)
167      */

168     public void setNodeValue(String JavaDoc value) {
169
170         setNodeValueInternal(value);
171
172         // notify document
173
ownerDocument().replacedText(this);
174     }
175
176     //
177
// CharacterData methods
178
//
179

180     /**
181      * Retrieve character data currently stored in this node.
182      *
183      * @throws DOMExcpetion(DOMSTRING_SIZE_ERR) In some implementations,
184      * the stored data may exceed the permitted length of strings. If so,
185      * getData() will throw this DOMException advising the user to
186      * instead retrieve the data in chunks via the substring() operation.
187      */

188     public String JavaDoc getData() {
189         if (needsSyncData()) {
190             synchronizeData();
191         }
192         return data;
193     }
194
195     /**
196      * Report number of characters currently stored in this node's
197      * data. It may be 0, meaning that the value is an empty string.
198      */

199     public int getLength() {
200         if (needsSyncData()) {
201             synchronizeData();
202         }
203         return data.length();
204     }
205
206     /**
207      * Concatenate additional characters onto the end of the data
208      * stored in this node. Note that this, and insert(), are the paths
209      * by which a DOM could wind up accumulating more data than the
210      * language's strings can easily handle. (See above discussion.)
211      *
212      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
213      */

214     public void appendData(String JavaDoc data) {
215
216         if (isReadOnly()) {
217             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
218             throw new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
219         }
220         if (data == null) {
221             return;
222         }
223         if (needsSyncData()) {
224             synchronizeData();
225         }
226         
227         setNodeValue(this.data + data);
228
229     } // appendData(String)
230

231     /**
232      * Remove a range of characters from the node's value. Throws a
233      * DOMException if the offset is beyond the end of the
234      * string. However, a deletion _count_ that exceeds the available
235      * data is accepted as a delete-to-end request.
236      *
237      * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
238      * greater than length, or if count is negative.
239      *
240      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is
241      * readonly.
242      */

243     public void deleteData(int offset, int count)
244         throws DOMException JavaDoc {
245
246         if (isReadOnly()) {
247             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
248             throw new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
249         }
250
251         if (count < 0) {
252             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
253             throw new DOMException JavaDoc(DOMException.INDEX_SIZE_ERR, msg);
254         }
255
256         if (needsSyncData()) {
257             synchronizeData();
258         }
259         int tailLength = Math.max(data.length() - count - offset, 0);
260         try {
261             String JavaDoc value = data.substring(0, offset) +
262                 (tailLength > 0
263                  ? data.substring(offset + count, offset + count + tailLength)
264                  : "");
265
266             setNodeValueInternal(value);
267
268             // notify document
269
ownerDocument().deletedText(this, offset, count);
270         }
271         catch (StringIndexOutOfBoundsException JavaDoc e) {
272             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
273             throw new DOMException JavaDoc(DOMException.INDEX_SIZE_ERR, msg);
274         }
275
276     } // deleteData(int,int)
277

278     /**
279      * Insert additional characters into the data stored in this node,
280      * at the offset specified.
281      *
282      * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
283      * greater than length.
284      *
285      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
286      */

287     public void insertData(int offset, String JavaDoc data)
288         throws DOMException JavaDoc {
289
290         if (isReadOnly()) {
291             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
292             throw new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
293         }
294
295         if (needsSyncData()) {
296             synchronizeData();
297         }
298         try {
299             String JavaDoc value =
300                 new StringBuffer JavaDoc(this.data).insert(offset, data).toString();
301
302             setNodeValueInternal(value);
303
304             // notify document
305
ownerDocument().insertedText(this, offset, data.length());
306         }
307         catch (StringIndexOutOfBoundsException JavaDoc e) {
308             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
309             throw new DOMException JavaDoc(DOMException.INDEX_SIZE_ERR, msg);
310         }
311
312     } // insertData(int,int)
313

314     /**
315      * Replace a series of characters at the specified (zero-based)
316      * offset with a new string, NOT necessarily of the same
317      * length. Convenience method, equivalent to a delete followed by an
318      * insert. Throws a DOMException if the specified offset is beyond
319      * the end of the existing data.
320      *
321      * @param offset The offset at which to begin replacing.
322      *
323      * @param count The number of characters to remove,
324      * interpreted as in the delete() method.
325      *
326      * @param data The new string to be inserted at offset in place of
327      * the removed data. Note that the entire string will
328      * be inserted -- the count parameter does not affect
329      * insertion, and the new data may be longer or shorter
330      * than the substring it replaces.
331      *
332      * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
333      * greater than length, or if count is negative.
334      *
335      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is
336      * readonly.
337      */

338     public void replaceData(int offset, int count, String JavaDoc data)
339         throws DOMException JavaDoc {
340
341         // The read-only check is done by deleteData()
342
// ***** This could be more efficient w/r/t Mutation Events,
343
// specifically by aggregating DOMAttrModified and
344
// DOMSubtreeModified. But mutation events are
345
// underspecified; I don't feel compelled
346
// to deal with it right now.
347
deleteData(offset, count);
348         insertData(offset, data);
349
350     } // replaceData(int,int,String)
351

352     /**
353      * Store character data into this node.
354      *
355      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
356      */

357     public void setData(String JavaDoc value)
358         throws DOMException JavaDoc {
359         setNodeValue(value);
360     }
361
362     /**
363      * Substring is more than a convenience function. In some
364      * implementations of the DOM, where the stored data may exceed the
365      * length that can be returned in a single string, the only way to
366      * read it all is to extract it in chunks via this method.
367      *
368      * @param offset Zero-based offset of first character to retrieve.
369      * @param count Number of characters to retrieve.
370      *
371      * If the sum of offset and count exceeds the length, all characters
372      * to end of data are returned.
373      *
374      * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
375      * greater than length, or if count is negative.
376      *
377      * @throws DOMException(WSTRING_SIZE_ERR) In some implementations,
378      * count may exceed the permitted length of strings. If so,
379      * substring() will throw this DOMException advising the user to
380      * instead retrieve the data in smaller chunks.
381      */

382     public String JavaDoc substringData(int offset, int count)
383         throws DOMException JavaDoc {
384
385         if (needsSyncData()) {
386             synchronizeData();
387         }
388         
389         int length = data.length();
390         if (count < 0 || offset < 0 || offset > length - 1) {
391             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
392             throw new DOMException JavaDoc(DOMException.INDEX_SIZE_ERR, msg);
393         }
394
395         int tailIndex = Math.min(offset + count, length);
396
397         return data.substring(offset, tailIndex);
398
399     } // substringData(int,int):String
400

401 } // class CharacterDataImpl
402
Popular Tags