KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ccil > cowan > tagsoup > AttributesImpl


1 // Our own copy, so we don't depend on possibly buggy reimplementations
2
// AttributesImpl.java - default implementation of Attributes.
3
// http://www.saxproject.org
4
// Written by David Megginson
5
// NO WARRANTY! This class is in the public domain.
6

7 // $Id: AttributesImpl.java,v 1.1 2002/11/06 21:30:14 cowan Exp cowan $
8

9
10
11 package org.ccil.cowan.tagsoup;
12 import org.xml.sax.Attributes JavaDoc;
13
14
15 /**
16  * Default implementation of the Attributes interface.
17  *
18  * <blockquote>
19  * <em>This module, both source code and documentation, is in the
20  * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
21  * See <a HREF='http://www.saxproject.org'>http://www.saxproject.org</a>
22  * for further information.
23  * </blockquote>
24  *
25  * <p>This class provides a default implementation of the SAX2
26  * {@link org.xml.sax.Attributes Attributes} interface, with the
27  * addition of manipulators so that the list can be modified or
28  * reused.</p>
29  *
30  * <p>There are two typical uses of this class:</p>
31  *
32  * <ol>
33  * <li>to take a persistent snapshot of an Attributes object
34  * in a {@link org.xml.sax.ContentHandler#startElement startElement} event; or</li>
35  * <li>to construct or modify an Attributes object in a SAX2 driver or filter.</li>
36  * </ol>
37  *
38  * <p>This class replaces the now-deprecated SAX1 {@link
39  * org.xml.sax.helpers.AttributeListImpl AttributeListImpl}
40  * class; in addition to supporting the updated Attributes
41  * interface rather than the deprecated {@link org.xml.sax.AttributeList
42  * AttributeList} interface, it also includes a much more efficient
43  * implementation using a single array rather than a set of Vectors.</p>
44  *
45  * @since SAX 2.0
46  * @author David Megginson
47  * @version 2.0.1 (sax2r2)
48  */

49 public class AttributesImpl implements Attributes JavaDoc
50 {
51
52
53     ////////////////////////////////////////////////////////////////////
54
// Constructors.
55
////////////////////////////////////////////////////////////////////
56

57
58     /**
59      * Construct a new, empty AttributesImpl object.
60      */

61     public AttributesImpl ()
62     {
63     length = 0;
64     data = null;
65     }
66
67
68     /**
69      * Copy an existing Attributes object.
70      *
71      * <p>This constructor is especially useful inside a
72      * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p>
73      *
74      * @param atts The existing Attributes object.
75      */

76     public AttributesImpl (Attributes JavaDoc atts)
77     {
78     setAttributes(atts);
79     }
80
81
82
83     ////////////////////////////////////////////////////////////////////
84
// Implementation of org.xml.sax.Attributes.
85
////////////////////////////////////////////////////////////////////
86

87
88     /**
89      * Return the number of attributes in the list.
90      *
91      * @return The number of attributes in the list.
92      * @see org.xml.sax.Attributes#getLength
93      */

94     public int getLength ()
95     {
96     return length;
97     }
98
99
100     /**
101      * Return an attribute's Namespace URI.
102      *
103      * @param index The attribute's index (zero-based).
104      * @return The Namespace URI, the empty string if none is
105      * available, or null if the index is out of range.
106      * @see org.xml.sax.Attributes#getURI
107      */

108     public String JavaDoc getURI (int index)
109     {
110     if (index >= 0 && index < length) {
111         return data[index*5];
112     } else {
113         return null;
114     }
115     }
116
117
118     /**
119      * Return an attribute's local name.
120      *
121      * @param index The attribute's index (zero-based).
122      * @return The attribute's local name, the empty string if
123      * none is available, or null if the index if out of range.
124      * @see org.xml.sax.Attributes#getLocalName
125      */

126     public String JavaDoc getLocalName (int index)
127     {
128     if (index >= 0 && index < length) {
129         return data[index*5+1];
130     } else {
131         return null;
132     }
133     }
134
135
136     /**
137      * Return an attribute's qualified (prefixed) name.
138      *
139      * @param index The attribute's index (zero-based).
140      * @return The attribute's qualified name, the empty string if
141      * none is available, or null if the index is out of bounds.
142      * @see org.xml.sax.Attributes#getQName
143      */

144     public String JavaDoc getQName (int index)
145     {
146     if (index >= 0 && index < length) {
147         return data[index*5+2];
148     } else {
149         return null;
150     }
151     }
152
153
154     /**
155      * Return an attribute's type by index.
156      *
157      * @param index The attribute's index (zero-based).
158      * @return The attribute's type, "CDATA" if the type is unknown, or null
159      * if the index is out of bounds.
160      * @see org.xml.sax.Attributes#getType(int)
161      */

162     public String JavaDoc getType (int index)
163     {
164     if (index >= 0 && index < length) {
165         return data[index*5+3];
166     } else {
167         return null;
168     }
169     }
170
171
172     /**
173      * Return an attribute's value by index.
174      *
175      * @param index The attribute's index (zero-based).
176      * @return The attribute's value or null if the index is out of bounds.
177      * @see org.xml.sax.Attributes#getValue(int)
178      */

179     public String JavaDoc getValue (int index)
180     {
181     if (index >= 0 && index < length) {
182         return data[index*5+4];
183     } else {
184         return null;
185     }
186     }
187
188
189     /**
190      * Look up an attribute's index by Namespace name.
191      *
192      * <p>In many cases, it will be more efficient to look up the name once and
193      * use the index query methods rather than using the name query methods
194      * repeatedly.</p>
195      *
196      * @param uri The attribute's Namespace URI, or the empty
197      * string if none is available.
198      * @param localName The attribute's local name.
199      * @return The attribute's index, or -1 if none matches.
200      * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
201      */

202     public int getIndex (String JavaDoc uri, String JavaDoc localName)
203     {
204     int max = length * 5;
205     for (int i = 0; i < max; i += 5) {
206         if (data[i].equals(uri) && data[i+1].equals(localName)) {
207         return i / 5;
208         }
209     }
210     return -1;
211     }
212
213
214     /**
215      * Look up an attribute's index by qualified (prefixed) name.
216      *
217      * @param qName The qualified name.
218      * @return The attribute's index, or -1 if none matches.
219      * @see org.xml.sax.Attributes#getIndex(java.lang.String)
220      */

221     public int getIndex (String JavaDoc qName)
222     {
223     int max = length * 5;
224     for (int i = 0; i < max; i += 5) {
225         if (data[i+2].equals(qName)) {
226         return i / 5;
227         }
228     }
229     return -1;
230     }
231
232
233     /**
234      * Look up an attribute's type by Namespace-qualified name.
235      *
236      * @param uri The Namespace URI, or the empty string for a name
237      * with no explicit Namespace URI.
238      * @param localName The local name.
239      * @return The attribute's type, or null if there is no
240      * matching attribute.
241      * @see org.xml.sax.Attributes#getType(java.lang.String,java.lang.String)
242      */

243     public String JavaDoc getType (String JavaDoc uri, String JavaDoc localName)
244     {
245     int max = length * 5;
246     for (int i = 0; i < max; i += 5) {
247         if (data[i].equals(uri) && data[i+1].equals(localName)) {
248         return data[i+3];
249         }
250     }
251     return null;
252     }
253
254
255     /**
256      * Look up an attribute's type by qualified (prefixed) name.
257      *
258      * @param qName The qualified name.
259      * @return The attribute's type, or null if there is no
260      * matching attribute.
261      * @see org.xml.sax.Attributes#getType(java.lang.String)
262      */

263     public String JavaDoc getType (String JavaDoc qName)
264     {
265     int max = length * 5;
266     for (int i = 0; i < max; i += 5) {
267         if (data[i+2].equals(qName)) {
268         return data[i+3];
269         }
270     }
271     return null;
272     }
273
274
275     /**
276      * Look up an attribute's value by Namespace-qualified name.
277      *
278      * @param uri The Namespace URI, or the empty string for a name
279      * with no explicit Namespace URI.
280      * @param localName The local name.
281      * @return The attribute's value, or null if there is no
282      * matching attribute.
283      * @see org.xml.sax.Attributes#getValue(java.lang.String,java.lang.String)
284      */

285     public String JavaDoc getValue (String JavaDoc uri, String JavaDoc localName)
286     {
287     int max = length * 5;
288     for (int i = 0; i < max; i += 5) {
289         if (data[i].equals(uri) && data[i+1].equals(localName)) {
290         return data[i+4];
291         }
292     }
293     return null;
294     }
295
296
297     /**
298      * Look up an attribute's value by qualified (prefixed) name.
299      *
300      * @param qName The qualified name.
301      * @return The attribute's value, or null if there is no
302      * matching attribute.
303      * @see org.xml.sax.Attributes#getValue(java.lang.String)
304      */

305     public String JavaDoc getValue (String JavaDoc qName)
306     {
307     int max = length * 5;
308     for (int i = 0; i < max; i += 5) {
309         if (data[i+2].equals(qName)) {
310         return data[i+4];
311         }
312     }
313     return null;
314     }
315
316
317
318     ////////////////////////////////////////////////////////////////////
319
// Manipulators.
320
////////////////////////////////////////////////////////////////////
321

322
323     /**
324      * Clear the attribute list for reuse.
325      *
326      * <p>Note that little memory is freed by this call:
327      * the current array is kept so it can be
328      * reused.</p>
329      */

330     public void clear ()
331     {
332     if (data != null) {
333         for (int i = 0; i < (length * 5); i++)
334         data [i] = null;
335     }
336     length = 0;
337     }
338
339
340     /**
341      * Copy an entire Attributes object.
342      *
343      * <p>It may be more efficient to reuse an existing object
344      * rather than constantly allocating new ones.</p>
345      *
346      * @param atts The attributes to copy.
347      */

348     public void setAttributes (Attributes JavaDoc atts)
349     {
350         clear();
351         length = atts.getLength();
352         if (length > 0) {
353             data = new String JavaDoc[length*5];
354             for (int i = 0; i < length; i++) {
355                 data[i*5] = atts.getURI(i);
356                 data[i*5+1] = atts.getLocalName(i);
357                 data[i*5+2] = atts.getQName(i);
358                 data[i*5+3] = atts.getType(i);
359                 data[i*5+4] = atts.getValue(i);
360             }
361     }
362     }
363
364
365     /**
366      * Add an attribute to the end of the list.
367      *
368      * <p>For the sake of speed, this method does no checking
369      * to see if the attribute is already in the list: that is
370      * the responsibility of the application.</p>
371      *
372      * @param uri The Namespace URI, or the empty string if
373      * none is available or Namespace processing is not
374      * being performed.
375      * @param localName The local name, or the empty string if
376      * Namespace processing is not being performed.
377      * @param qName The qualified (prefixed) name, or the empty string
378      * if qualified names are not available.
379      * @param type The attribute type as a string.
380      * @param value The attribute value.
381      */

382     public void addAttribute (String JavaDoc uri, String JavaDoc localName, String JavaDoc qName,
383                   String JavaDoc type, String JavaDoc value)
384     {
385     ensureCapacity(length+1);
386     data[length*5] = uri;
387     data[length*5+1] = localName;
388     data[length*5+2] = qName;
389     data[length*5+3] = type;
390     data[length*5+4] = value;
391     length++;
392     }
393
394
395     /**
396      * Set an attribute in the list.
397      *
398      * <p>For the sake of speed, this method does no checking
399      * for name conflicts or well-formedness: such checks are the
400      * responsibility of the application.</p>
401      *
402      * @param index The index of the attribute (zero-based).
403      * @param uri The Namespace URI, or the empty string if
404      * none is available or Namespace processing is not
405      * being performed.
406      * @param localName The local name, or the empty string if
407      * Namespace processing is not being performed.
408      * @param qName The qualified name, or the empty string
409      * if qualified names are not available.
410      * @param type The attribute type as a string.
411      * @param value The attribute value.
412      * @exception java.lang.ArrayIndexOutOfBoundsException When the
413      * supplied index does not point to an attribute
414      * in the list.
415      */

416     public void setAttribute (int index, String JavaDoc uri, String JavaDoc localName,
417                   String JavaDoc qName, String JavaDoc type, String JavaDoc value)
418     {
419     if (index >= 0 && index < length) {
420         data[index*5] = uri;
421         data[index*5+1] = localName;
422         data[index*5+2] = qName;
423         data[index*5+3] = type;
424         data[index*5+4] = value;
425     } else {
426         badIndex(index);
427     }
428     }
429
430
431     /**
432      * Remove an attribute from the list.
433      *
434      * @param index The index of the attribute (zero-based).
435      * @exception java.lang.ArrayIndexOutOfBoundsException When the
436      * supplied index does not point to an attribute
437      * in the list.
438      */

439     public void removeAttribute (int index)
440     {
441     if (index >= 0 && index < length) {
442         if (index < length - 1) {
443         System.arraycopy(data, (index+1)*5, data, index*5,
444                  (length-index-1)*5);
445         }
446         index = (length - 1) * 5;
447         data [index++] = null;
448         data [index++] = null;
449         data [index++] = null;
450         data [index++] = null;
451         data [index] = null;
452         length--;
453     } else {
454         badIndex(index);
455     }
456     }
457
458
459     /**
460      * Set the Namespace URI of a specific attribute.
461      *
462      * @param index The index of the attribute (zero-based).
463      * @param uri The attribute's Namespace URI, or the empty
464      * string for none.
465      * @exception java.lang.ArrayIndexOutOfBoundsException When the
466      * supplied index does not point to an attribute
467      * in the list.
468      */

469     public void setURI (int index, String JavaDoc uri)
470     {
471     if (index >= 0 && index < length) {
472         data[index*5] = uri;
473     } else {
474         badIndex(index);
475     }
476     }
477
478
479     /**
480      * Set the local name of a specific attribute.
481      *
482      * @param index The index of the attribute (zero-based).
483      * @param localName The attribute's local name, or the empty
484      * string for none.
485      * @exception java.lang.ArrayIndexOutOfBoundsException When the
486      * supplied index does not point to an attribute
487      * in the list.
488      */

489     public void setLocalName (int index, String JavaDoc localName)
490     {
491     if (index >= 0 && index < length) {
492         data[index*5+1] = localName;
493     } else {
494         badIndex(index);
495     }
496     }
497
498
499     /**
500      * Set the qualified name of a specific attribute.
501      *
502      * @param index The index of the attribute (zero-based).
503      * @param qName The attribute's qualified name, or the empty
504      * string for none.
505      * @exception java.lang.ArrayIndexOutOfBoundsException When the
506      * supplied index does not point to an attribute
507      * in the list.
508      */

509     public void setQName (int index, String JavaDoc qName)
510     {
511     if (index >= 0 && index < length) {
512         data[index*5+2] = qName;
513     } else {
514         badIndex(index);
515     }
516     }
517
518
519     /**
520      * Set the type of a specific attribute.
521      *
522      * @param index The index of the attribute (zero-based).
523      * @param type The attribute's type.
524      * @exception java.lang.ArrayIndexOutOfBoundsException When the
525      * supplied index does not point to an attribute
526      * in the list.
527      */

528     public void setType (int index, String JavaDoc type)
529     {
530     if (index >= 0 && index < length) {
531         data[index*5+3] = type;
532     } else {
533         badIndex(index);
534     }
535     }
536
537
538     /**
539      * Set the value of a specific attribute.
540      *
541      * @param index The index of the attribute (zero-based).
542      * @param value The attribute's value.
543      * @exception java.lang.ArrayIndexOutOfBoundsException When the
544      * supplied index does not point to an attribute
545      * in the list.
546      */

547     public void setValue (int index, String JavaDoc value)
548     {
549     if (index >= 0 && index < length) {
550         data[index*5+4] = value;
551     } else {
552         badIndex(index);
553     }
554     }
555
556
557
558     ////////////////////////////////////////////////////////////////////
559
// Internal methods.
560
////////////////////////////////////////////////////////////////////
561

562
563     /**
564      * Ensure the internal array's capacity.
565      *
566      * @param n The minimum number of attributes that the array must
567      * be able to hold.
568      */

569     private void ensureCapacity (int n) {
570         if (n <= 0) {
571             return;
572         }
573         int max;
574         if (data == null || data.length == 0) {
575             max = 25;
576         }
577         else if (data.length >= n * 5) {
578             return;
579         }
580         else {
581             max = data.length;
582         }
583         while (max < n * 5) {
584             max *= 2;
585         }
586
587         String JavaDoc newData[] = new String JavaDoc[max];
588         if (length > 0) {
589             System.arraycopy(data, 0, newData, 0, length*5);
590         }
591         data = newData;
592     }
593
594
595     /**
596      * Report a bad array index in a manipulator.
597      *
598      * @param index The index to report.
599      * @exception java.lang.ArrayIndexOutOfBoundsException Always.
600      */

601     private void badIndex (int index)
602     throws ArrayIndexOutOfBoundsException JavaDoc
603     {
604     String JavaDoc msg =
605         "Attempt to modify attribute at illegal index: " + index;
606     throw new ArrayIndexOutOfBoundsException JavaDoc(msg);
607     }
608
609
610
611     ////////////////////////////////////////////////////////////////////
612
// Internal state.
613
////////////////////////////////////////////////////////////////////
614

615     int length;
616     String JavaDoc data [];
617
618 }
619
620 // end of AttributesImpl.java
621

622
Popular Tags