KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > xpath > datamodel > xerces > dom > CharacterDataImpl


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999 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 org.xquark.xpath.datamodel.xerces.dom;
59
60 import org.w3c.dom.DOMException JavaDoc;
61 import org.w3c.dom.Node JavaDoc;
62 import org.w3c.dom.NodeList JavaDoc;
63 import org.w3c.dom.events.MutationEvent JavaDoc;
64 import org.xquark.xpath.datamodel.xerces.dom.events.MutationEventImpl;
65
66 /**
67  * CharacterData is an abstract Node that can carry character data as its
68  * Value. It provides shared behavior for Text, CData, and
69  * possibly other node types. All offsets are 0-based.
70  * <p>
71  * This implementation includes support for DOM Level 2 Mutation Events.
72  * If the static boolean NodeImpl.MUTATIONEVENTS is not set true, that support
73  * is disabled and can be optimized out to reduce code size.
74  *
75  * Since this ProcessingInstructionImpl inherits from this class to reuse the
76  * setNodeValue method, this class isn't declared as implementing the interface
77  * CharacterData. This is done by relevant subclasses (TexImpl, CommentImpl).
78  *
79  * @version
80  * @since PR-DOM-Level-1-19980818.
81  */

82 public abstract class CharacterDataImpl
83     extends ChildNode {
84
85     //
86
// Constants
87
//
88

89     /** Serialization version. */
90     static final long serialVersionUID = 7931170150428474230L;
91
92     //
93
// Data
94
//
95

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

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

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

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

140     void setNodeValueInternal(String JavaDoc value) {
141         /** flag to indicate whether setNodeValue was called by the
142          * client or from the DOM.
143          */

144         setValueCalled(true);
145         setNodeValue(value);
146         setValueCalled(false);
147     }
148     
149     /**
150      * Sets the content, possibly firing related events,
151      * and updating ranges (via notification to the document)
152      */

153     public void setNodeValue(String JavaDoc value) {
154         if (isReadOnly())
155             throw new DOMException JavaDoc(
156                 DOMException.NO_MODIFICATION_ALLOWED_ERR,
157                 "DOM001 Modification not allowed");
158         // revisit: may want to set the value in ownerDocument.
159
// Default behavior, overridden in some subclasses
160
if (needsSyncData()) {
161             synchronizeData();
162         }
163             
164         // Cache old value for DOMCharacterDataModified.
165
String JavaDoc oldvalue = this.data;
166         EnclosingAttr enclosingAttr=null;
167         if(MUTATIONEVENTS)
168         {
169             // MUTATION PREPROCESSING AND PRE-EVENTS:
170
// If we're within the scope of an Attr and DOMAttrModified
171
// was requested, we need to preserve its previous value for
172
// that event.
173
LCount lc=LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
174             if(lc.captures+lc.bubbles+lc.defaults>0)
175             {
176                 enclosingAttr=getEnclosingAttr();
177             }
178         } // End mutation preprocessing
179

180         this.data = value;
181         if (!setValueCalled()) {
182             // notify document
183
ownerDocument().replacedText(this);
184         }
185         
186         if(MUTATIONEVENTS)
187         {
188             // MUTATION POST-EVENTS:
189
LCount lc =
190                 LCount.lookup(MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED);
191             if(lc.captures+lc.bubbles+lc.defaults>0)
192             {
193                 MutationEvent JavaDoc me= new MutationEventImpl();
194                 me.initMutationEvent(
195                                  MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED,
196                                  true,false,null,oldvalue,value,null,(short)0);
197                 dispatchEvent(me);
198             }
199             
200             // Subroutine: Transmit DOMAttrModified and DOMSubtreeModified,
201
// if required. (Common to most kinds of mutation)
202
dispatchAggregateEvents(enclosingAttr);
203         } // End mutation postprocessing
204

205     } // setNodeValue(String)
206

207     //
208
// CharacterData methods
209
//
210

211     /**
212      * Retrieve character data currently stored in this node.
213      *
214      * @throws DOMExcpetion(DOMSTRING_SIZE_ERR) In some implementations,
215      * the stored data may exceed the permitted length of strings. If so,
216      * getData() will throw this DOMException advising the user to
217      * instead retrieve the data in chunks via the substring() operation.
218      */

219     public String JavaDoc getData() {
220         if (needsSyncData()) {
221             synchronizeData();
222         }
223         return data;
224     }
225
226     /**
227      * Report number of characters currently stored in this node's
228      * data. It may be 0, meaning that the value is an empty string.
229      */

230     public int getLength() {
231         if (needsSyncData()) {
232             synchronizeData();
233         }
234         return data.length();
235     }
236
237     /**
238      * Concatenate additional characters onto the end of the data
239      * stored in this node. Note that this, and insert(), are the paths
240      * by which a DOM could wind up accumulating more data than the
241      * language's strings can easily handle. (See above discussion.)
242      *
243      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
244      */

245     public void appendData(String JavaDoc data) {
246
247         if (isReadOnly()) {
248             throw new DOMException JavaDoc(
249                 DOMException.NO_MODIFICATION_ALLOWED_ERR,
250                 "DOM001 Modification not allowed");
251         }
252
253         if (needsSyncData()) {
254             synchronizeData();
255         }
256         
257         // Handles mutation event generation, if any
258
setNodeValue(this.data + data);
259
260     } // appendData(String)
261

262     /**
263      * Remove a range of characters from the node's value. Throws a
264      * DOMException if the offset is beyond the end of the
265      * string. However, a deletion _count_ that exceeds the available
266      * data is accepted as a delete-to-end request.
267      *
268      * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
269      * greater than length, or if count is negative.
270      *
271      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is
272      * readonly.
273      */

274     public void deleteData(int offset, int count)
275         throws DOMException JavaDoc {
276
277         if (isReadOnly()) {
278             throw new DOMException JavaDoc(
279                 DOMException.NO_MODIFICATION_ALLOWED_ERR,
280                 "DOM001 Modification not allowed");
281         }
282
283         if (count < 0) {
284             throw new DOMException JavaDoc(DOMException.INDEX_SIZE_ERR,
285                                        "DOM004 Index out of bounds");
286         }
287
288         if (needsSyncData()) {
289             synchronizeData();
290         }
291         int tailLength = Math.max(data.length() - count - offset, 0);
292         try {
293             // Handles mutation event generation, if any
294
setNodeValueInternal(data.substring(0, offset) +
295                                  (tailLength > 0
296         ? data.substring(offset + count, offset + count + tailLength)
297                                   : "") );
298             // notify document
299
ownerDocument().deletedText(this, offset, count);
300         }
301         catch (StringIndexOutOfBoundsException JavaDoc e) {
302             throw new DOMException JavaDoc(DOMException.INDEX_SIZE_ERR,
303                                        "DOM004 Index out of bounds");
304         }
305
306     } // deleteData(int,int)
307

308     /**
309      * Insert additional characters into the data stored in this node,
310      * at the offset specified.
311      *
312      * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
313      * greater than length.
314      *
315      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
316      */

317     public void insertData(int offset, String JavaDoc data)
318         throws DOMException JavaDoc {
319
320         if (isReadOnly()) {
321             throw new DOMException JavaDoc(
322                 DOMException.NO_MODIFICATION_ALLOWED_ERR,
323                 "DOM001 Modification not allowed");
324         }
325
326         if (needsSyncData()) {
327             synchronizeData();
328         }
329         try {
330             // Handles mutation event generation, if any
331
setNodeValueInternal(
332                 new StringBuffer JavaDoc(this.data).insert(offset, data).toString()
333                 );
334             // notify document
335
ownerDocument().insertedText(this, offset, data.length());
336         }
337         catch (StringIndexOutOfBoundsException JavaDoc e) {
338             throw new DOMException JavaDoc(DOMException.INDEX_SIZE_ERR,
339                                        "DOM004 Index out of bounds");
340         }
341
342     } // insertData(int,int)
343

344     /**
345      * Replace a series of characters at the specified (zero-based)
346      * offset with a new string, NOT necessarily of the same
347      * length. Convenience method, equivalent to a delete followed by an
348      * insert. Throws a DOMException if the specified offset is beyond
349      * the end of the existing data.
350      *
351      * @param offset The offset at which to begin replacing.
352      *
353      * @param count The number of characters to remove,
354      * interpreted as in the delete() method.
355      *
356      * @param data The new string to be inserted at offset in place of
357      * the removed data. Note that the entire string will
358      * be inserted -- the count parameter does not affect
359      * insertion, and the new data may be longer or shorter
360      * than the substring it replaces.
361      *
362      * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
363      * greater than length, or if count is negative.
364      *
365      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is
366      * readonly.
367      */

368     public void replaceData(int offset, int count, String JavaDoc data)
369         throws DOMException JavaDoc {
370
371         // The read-only check is done by deleteData()
372
// ***** This could be more efficient w/r/t Mutation Events,
373
// specifically by aggregating DOMAttrModified and
374
// DOMSubtreeModified. But mutation events are
375
// underspecified; I don't feel compelled
376
// to deal with it right now.
377
deleteData(offset, count);
378         insertData(offset, data);
379
380     } // replaceData(int,int,String)
381

382     /**
383      * Store character data into this node.
384      *
385      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
386      */

387     public void setData(String JavaDoc value)
388         throws DOMException JavaDoc {
389         setNodeValue(value);
390     }
391
392     /**
393      * Substring is more than a convenience function. In some
394      * implementations of the DOM, where the stored data may exceed the
395      * length that can be returned in a single string, the only way to
396      * read it all is to extract it in chunks via this method.
397      *
398      * @param offset Zero-based offset of first character to retrieve.
399      * @param count Number of characters to retrieve.
400      *
401      * If the sum of offset and count exceeds the length, all characters
402      * to end of data are returned.
403      *
404      * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
405      * greater than length, or if count is negative.
406      *
407      * @throws DOMException(WSTRING_SIZE_ERR) In some implementations,
408      * count may exceed the permitted length of strings. If so,
409      * substring() will throw this DOMException advising the user to
410      * instead retrieve the data in smaller chunks.
411      */

412     public String JavaDoc substringData(int offset, int count)
413         throws DOMException JavaDoc {
414
415         if (needsSyncData()) {
416             synchronizeData();
417         }
418         
419         int length = data.length();
420         if (count < 0 || offset < 0 || offset > length - 1) {
421             throw new DOMException JavaDoc(DOMException.INDEX_SIZE_ERR,
422                                        "DOM004 Index out of bounds");
423         }
424
425         int tailIndex = Math.min(offset + count, length);
426
427         return data.substring(offset, tailIndex);
428
429     } // substringData(int,int):String
430

431 } // class CharacterDataImpl
432
Popular Tags