OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / lib / classpath / external / sax / org / xml / sax / helpers / AttributesImpl.java
1 // AttributesImpl.java - default implementation of Attributes.
2 // http://www.saxproject.org
3 // Written by David Megginson
4 // NO WARRANTY!  This class is in the public domain.
5 // $Id: AttributesImpl.java,v 1.1 2004/12/23 22:38:42 mark Exp $
6
7 package org.xml.sax.helpers;
8
9 import org.xml.sax.Attributes;
10
11
12 /**
13  * Default implementation of the Attributes interface.
14  *
15  * <blockquote>
16  * <em>This module, both source code and documentation, is in the
17  * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
18  * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
19  * for further information.
20  * </blockquote>
21  *
22  * <p>This class provides a default implementation of the SAX2
23  * {@link org.xml.sax.Attributes Attributes} interface, with the 
24  * addition of manipulators so that the list can be modified or 
25  * reused.</p>
26  *
27  * <p>There are two typical uses of this class:</p>
28  *
29  * <ol>
30  * <li>to take a persistent snapshot of an Attributes object
31  *  in a {@link org.xml.sax.ContentHandler#startElement startElement} event; or</li>
32  * <li>to construct or modify an Attributes object in a SAX2 driver or filter.</li>
33  * </ol>
34  *
35  * <p>This class replaces the now-deprecated SAX1 {@link 
36  * org.xml.sax.helpers.AttributeListImpl AttributeListImpl}
37  * class; in addition to supporting the updated Attributes
38  * interface rather than the deprecated {@link org.xml.sax.AttributeList
39  * AttributeList} interface, it also includes a much more efficient 
40  * implementation using a single array rather than a set of Vectors.</p>
41  *
42  * @since SAX 2.0
43  * @author David Megginson
44  * @version 2.0.1 (sax2r2)
45  */
46 public class AttributesImpl implements Attributes
47 {
48
49 \f
50     ////////////////////////////////////////////////////////////////////
51     // Constructors.
52     ////////////////////////////////////////////////////////////////////
53
54
55     /**
56      * Construct a new, empty AttributesImpl object.
57      */
58     public AttributesImpl ()
59     {
60         length = 0;
61         data = null;
62     }
63
64
65     /**
66      * Copy an existing Attributes object.
67      *
68      * <p>This constructor is especially useful inside a
69      * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p>
70      *
71      * @param atts The existing Attributes object.
72      */
73     public AttributesImpl (Attributes atts)
74     {
75         setAttributes(atts);
76     }
77
78
79 \f
80     ////////////////////////////////////////////////////////////////////
81     // Implementation of org.xml.sax.Attributes.
82     ////////////////////////////////////////////////////////////////////
83
84
85     /**
86      * Return the number of attributes in the list.
87      *
88      * @return The number of attributes in the list.
89      * @see org.xml.sax.Attributes#getLength
90      */
91     public int getLength ()
92     {
93         return length;
94     }
95
96
97     /**
98      * Return an attribute's Namespace URI.
99      *
100      * @param index The attribute's index (zero-based).
101      * @return The Namespace URI, the empty string if none is
102      *         available, or null if the index is out of range.
103      * @see org.xml.sax.Attributes#getURI
104      */
105     public String getURI (int index)
106     {
107         if (index >= 0 && index < length) {
108             return data[index*5];
109         } else {
110             return null;
111         }
112     }
113
114
115     /**
116      * Return an attribute's local name.
117      *
118      * @param index The attribute's index (zero-based).
119      * @return The attribute's local name, the empty string if 
120      *         none is available, or null if the index if out of range.
121      * @see org.xml.sax.Attributes#getLocalName
122      */
123     public String getLocalName (int index)
124     {
125         if (index >= 0 && index < length) {
126             return data[index*5+1];
127         } else {
128             return null;
129         }
130     }
131
132
133     /**
134      * Return an attribute's qualified (prefixed) name.
135      *
136      * @param index The attribute's index (zero-based).
137      * @return The attribute's qualified name, the empty string if 
138      *         none is available, or null if the index is out of bounds.
139      * @see org.xml.sax.Attributes#getQName
140      */
141     public String getQName (int index)
142     {
143         if (index >= 0 && index < length) {
144             return data[index*5+2];
145         } else {
146             return null;
147         }
148     }
149
150
151     /**
152      * Return an attribute's type by index.
153      *
154      * @param index The attribute's index (zero-based).
155      * @return The attribute's type, "CDATA" if the type is unknown, or null
156      *         if the index is out of bounds.
157      * @see org.xml.sax.Attributes#getType(int)
158      */
159     public String getType (int index)
160     {
161         if (index >= 0 && index < length) {
162             return data[index*5+3];
163         } else {
164             return null;
165         }
166     }
167
168
169     /**
170      * Return an attribute's value by index.
171      *
172      * @param index The attribute's index (zero-based).
173      * @return The attribute's value or null if the index is out of bounds.
174      * @see org.xml.sax.Attributes#getValue(int)
175      */
176     public String getValue (int index)
177     {
178         if (index >= 0 && index < length) {
179             return data[index*5+4];
180         } else {
181             return null;
182         }
183     }
184
185
186     /**
187      * Look up an attribute's index by Namespace name.
188      *
189      * <p>In many cases, it will be more efficient to look up the name once and
190      * use the index query methods rather than using the name query methods
191      * repeatedly.</p>
192      *
193      * @param uri The attribute's Namespace URI, or the empty
194      *        string if none is available.
195      * @param localName The attribute's local name.
196      * @return The attribute's index, or -1 if none matches.
197      * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
198      */
199     public int getIndex (String uri, String localName)
200     {
201         int max = length * 5;
202         for (int i = 0; i < max; i += 5) {
203             if (data[i].equals(uri) && data[i+1].equals(localName)) {
204                 return i / 5;
205             }
206         } 
207         return -1;
208     }
209
210
211     /**
212      * Look up an attribute's index by qualified (prefixed) name.
213      *
214      * @param qName The qualified name.
215      * @return The attribute's index, or -1 if none matches.
216      * @see org.xml.sax.Attributes#getIndex(java.lang.String)
217      */
218     public int getIndex (String qName)
219     {
220         int max = length * 5;
221         for (int i = 0; i < max; i += 5) {
222             if (data[i+2].equals(qName)) {
223                 return i / 5;
224             }
225         } 
226         return -1;
227     }
228
229
230     /**
231      * Look up an attribute's type by Namespace-qualified name.
232      *
233      * @param uri The Namespace URI, or the empty string for a name
234      *        with no explicit Namespace URI.
235      * @param localName The local name.
236      * @return The attribute's type, or null if there is no
237      *         matching attribute.
238      * @see org.xml.sax.Attributes#getType(java.lang.String,java.lang.String)
239      */
240     public String getType (String uri, String localName)
241     {
242         int max = length * 5;
243         for (int i = 0; i < max; i += 5) {
244             if (data[i].equals(uri) && data[i+1].equals(localName)) {
245                 return data[i+3];
246             }
247         } 
248         return null;
249     }
250
251
252     /**
253      * Look up an attribute's type by qualified (prefixed) name.
254      *
255      * @param qName The qualified name.
256      * @return The attribute's type, or null if there is no
257      *         matching attribute.
258      * @see org.xml.sax.Attributes#getType(java.lang.String)
259      */
260     public String getType (String qName)
261     {
262         int max = length * 5;
263         for (int i = 0; i < max; i += 5) {
264             if (data[i+2].equals(qName)) {
265                 return data[i+3];
266             }
267         }
268         return null;
269     }
270
271
272     /**
273      * Look up an attribute's value by Namespace-qualified name.
274      *
275      * @param uri The Namespace URI, or the empty string for a name
276      *        with no explicit Namespace URI.
277      * @param localName The local name.
278      * @return The attribute's value, or null if there is no
279      *         matching attribute.
280      * @see org.xml.sax.Attributes#getValue(java.lang.String,java.lang.String)
281      */
282     public String getValue (String uri, String localName)
283     {
284         int max = length * 5;
285         for (int i = 0; i < max; i += 5) {
286             if (data[i].equals(uri) && data[i+1].equals(localName)) {
287                 return data[i+4];
288             }
289         }
290         return null;
291     }
292
293
294     /**
295      * Look up an attribute's value by qualified (prefixed) name.
296      *
297      * @param qName The qualified name.
298      * @return The attribute's value, or null if there is no
299      *         matching attribute.
300      * @see org.xml.sax.Attributes#getValue(java.lang.String)
301      */
302     public String getValue (String qName)
303     {
304         int max = length * 5;
305         for (int i = 0; i < max; i += 5) {
306             if (data[i+2].equals(qName)) {
307                 return data[i+4];
308             }
309         }
310         return null;
311     }
312
313
314 \f
315     ////////////////////////////////////////////////////////////////////
316     // Manipulators.
317     ////////////////////////////////////////////////////////////////////
318
319
320     /**
321      * Clear the attribute list for reuse.
322      *
323      * <p>Note that little memory is freed by this call:
324      * the current array is kept so it can be 
325      * reused.</p>
326      */
327     public void clear ()
328     {
329         if (data != null) {
330             for (int i = 0; i < (length * 5); i++)
331                 data [i] = null;
332         }
333         length = 0;
334     }
335
336
337     /**
338      * Copy an entire Attributes object.
339      *
340      * <p>It may be more efficient to reuse an existing object
341      * rather than constantly allocating new ones.</p>
342      * 
343      * @param atts The attributes to copy.
344      */
345     public void setAttributes (Attributes atts)
346     {
347         clear();
348         length = atts.getLength();
349         if (length > 0) {
350             data = new String[length*5];
351             for (int i = 0; i < length; i++) {
352                 data[i*5] = atts.getURI(i);
353                 data[i*5+1] = atts.getLocalName(i);
354                 data[i*5+2] = atts.getQName(i);
355                 data[i*5+3] = atts.getType(i);
356                 data[i*5+4] = atts.getValue(i);
357             }
358         }
359     }
360
361
362     /**
363      * Add an attribute to the end of the list.
364      *
365      * <p>For the sake of speed, this method does no checking
366      * to see if the attribute is already in the list: that is
367      * the responsibility of the application.</p>
368      *
369      * @param uri The Namespace URI, or the empty string if
370      *        none is available or Namespace processing is not
371      *        being performed.
372      * @param localName The local name, or the empty string if
373      *        Namespace processing is not being performed.
374      * @param qName The qualified (prefixed) name, or the empty string
375      *        if qualified names are not available.
376      * @param type The attribute type as a string.
377      * @param value The attribute value.
378      */
379     public void addAttribute (String uri, String localName, String qName,
380                               String type, String value)
381     {
382         ensureCapacity(length+1);
383         data[length*5] = uri;
384         data[length*5+1] = localName;
385         data[length*5+2] = qName;
386         data[length*5+3] = type;
387         data[length*5+4] = value;
388         length++;
389     }
390
391
392     /**
393      * Set an attribute in the list.
394      *
395      * <p>For the sake of speed, this method does no checking
396      * for name conflicts or well-formedness: such checks are the
397      * responsibility of the application.</p>
398      *
399      * @param index The index of the attribute (zero-based).
400      * @param uri The Namespace URI, or the empty string if
401      *        none is available or Namespace processing is not
402      *        being performed.
403      * @param localName The local name, or the empty string if
404      *        Namespace processing is not being performed.
405      * @param qName The qualified name, or the empty string
406      *        if qualified names are not available.
407      * @param type The attribute type as a string.
408      * @param value The attribute value.
409      * @exception java.lang.ArrayIndexOutOfBoundsException When the
410      *            supplied index does not point to an attribute
411      *            in the list.
412      */
413     public void setAttribute (int index, String uri, String localName,
414                               String qName, String type, String value)
415     {
416         if (index >= 0 && index < length) {
417             data[index*5] = uri;
418             data[index*5+1] = localName;
419             data[index*5+2] = qName;
420             data[index*5+3] = type;
421             data[index*5+4] = value;
422         } else {
423             badIndex(index);
424         }
425     }
426
427
428     /**
429      * Remove an attribute from the list.
430      *
431      * @param index The index of the attribute (zero-based).
432      * @exception java.lang.ArrayIndexOutOfBoundsException When the
433      *            supplied index does not point to an attribute
434      *            in the list.
435      */
436     public void removeAttribute (int index)
437     {
438         if (index >= 0 && index < length) {
439             if (index < length - 1) {
440                 System.arraycopy(data, (index+1)*5, data, index*5,
441                                  (length-index-1)*5);
442             }
443             index = (length - 1) * 5;
444             data [index++] = null;
445             data [index++] = null;
446             data [index++] = null;
447             data [index++] = null;
448             data [index] = null;
449             length--;
450         } else {
451             badIndex(index);
452         }
453     }
454
455
456     /**
457      * Set the Namespace URI of a specific attribute.
458      *
459      * @param index The index of the attribute (zero-based).
460      * @param uri The attribute's Namespace URI, or the empty
461      *        string for none.
462      * @exception java.lang.ArrayIndexOutOfBoundsException When the
463      *            supplied index does not point to an attribute
464      *            in the list.
465      */
466     public void setURI (int index, String uri)
467     {
468         if (index >= 0 && index < length) {
469             data[index*5] = uri;
470         } else {
471             badIndex(index);
472         }
473     }
474
475
476     /**
477      * Set the local name of a specific attribute.
478      *
479      * @param index The index of the attribute (zero-based).
480      * @param localName The attribute's local name, or the empty
481      *        string for none.
482      * @exception java.lang.ArrayIndexOutOfBoundsException When the
483      *            supplied index does not point to an attribute
484      *            in the list.
485      */
486     public void setLocalName (int index, String localName)
487     {
488         if (index >= 0 && index < length) {
489             data[index*5+1] = localName;
490         } else {
491             badIndex(index);
492         }
493     }
494
495
496     /**
497      * Set the qualified name of a specific attribute.
498      *
499      * @param index The index of the attribute (zero-based).
500      * @param qName The attribute's qualified name, or the empty
501      *        string for none.
502      * @exception java.lang.ArrayIndexOutOfBoundsException When the
503      *            supplied index does not point to an attribute
504      *            in the list.
505      */
506     public void setQName (int index, String qName)
507     {
508         if (index >= 0 && index < length) {
509             data[index*5+2] = qName;
510         } else {
511             badIndex(index);
512         }
513     }
514
515
516     /**
517      * Set the type of a specific attribute.
518      *
519      * @param index The index of the attribute (zero-based).
520      * @param type The attribute's type.
521      * @exception java.lang.ArrayIndexOutOfBoundsException When the
522      *            supplied index does not point to an attribute
523      *            in the list.
524      */
525     public void setType (int index, String type)
526     {
527         if (index >= 0 && index < length) {
528             data[index*5+3] = type;
529         } else {
530             badIndex(index);
531         }
532     }
533
534
535     /**
536      * Set the value of a specific attribute.
537      *
538      * @param index The index of the attribute (zero-based).
539      * @param value The attribute's value.
540      * @exception java.lang.ArrayIndexOutOfBoundsException When the
541      *            supplied index does not point to an attribute
542      *            in the list.
543      */
544     public void setValue (int index, String value)
545     {
546         if (index >= 0 && index < length) {
547             data[index*5+4] = value;
548         } else {
549             badIndex(index);
550         }
551     }
552
553
554 \f
555     ////////////////////////////////////////////////////////////////////
556     // Internal methods.
557     ////////////////////////////////////////////////////////////////////
558
559
560     /**
561      * Ensure the internal array's capacity.
562      *
563      * @param n The minimum number of attributes that the array must
564      *        be able to hold.
565      */
566     private void ensureCapacity (int n)    {
567         if (n <= 0) {
568             return;
569         }
570         int max;
571         if (data == null || data.length == 0) {
572             max = 25;
573         }
574         else if (data.length >= n * 5) {
575             return;
576         }
577         else {
578             max = data.length;
579         }
580         while (max < n * 5) {
581             max *= 2;
582         }
583
584         String newData[] = new String[max];
585         if (length > 0) {
586             System.arraycopy(data, 0, newData, 0, length*5);
587         }
588         data = newData;
589     }
590
591
592     /**
593      * Report a bad array index in a manipulator.
594      *
595      * @param index The index to report.
596      * @exception java.lang.ArrayIndexOutOfBoundsException Always.
597      */
598     private void badIndex (int index)
599         throws ArrayIndexOutOfBoundsException
600     {
601         String msg =
602             "Attempt to modify attribute at illegal index: " + index;
603         throw new ArrayIndexOutOfBoundsException(msg);
604     }
605
606
607 \f
608     ////////////////////////////////////////////////////////////////////
609     // Internal state.
610     ////////////////////////////////////////////////////////////////////
611
612     int length;
613     String data [];
614
615 }
616
617 // end of AttributesImpl.java
618