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.
6 // $Id: AttributesImpl.java,v 1.6.2.3 2002/01/29 21:34:14 dbrownell Exp $
9 package org
.xml
.sax
.helpers
;
11 import org
.xml
.sax
.Attributes
;
15 * Default implementation of the Attributes interface.
18 * <em>This module, both source code and documentation, is in the
19 * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
20 * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
21 * for further information.
24 * <p>This class provides a default implementation of the SAX2
25 * {@link org.xml.sax.Attributes Attributes} interface, with the
26 * addition of manipulators so that the list can be modified or
29 * <p>There are two typical uses of this class:</p>
32 * <li>to take a persistent snapshot of an Attributes object
33 * in a {@link org.xml.sax.ContentHandler#startElement startElement} event; or</li>
34 * <li>to construct or modify an Attributes object in a SAX2 driver or filter.</li>
37 * <p>This class replaces the now-deprecated SAX1 {@link
38 * org.xml.sax.helpers.AttributeListImpl AttributeListImpl}
39 * class; in addition to supporting the updated Attributes
40 * interface rather than the deprecated {@link org.xml.sax.AttributeList
41 * AttributeList} interface, it also includes a much more efficient
42 * implementation using a single array rather than a set of Vectors.</p>
45 * @author David Megginson
46 * @version 2.0.1 (sax2r2)
48 public class AttributesImpl
implements Attributes
52 ////////////////////////////////////////////////////////////////////
54 ////////////////////////////////////////////////////////////////////
58 * Construct a new, empty AttributesImpl object.
60 public AttributesImpl ()
68 * Copy an existing Attributes object.
70 * <p>This constructor is especially useful inside a
71 * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p>
73 * @param atts The existing Attributes object.
75 public AttributesImpl (Attributes atts
)
82 ////////////////////////////////////////////////////////////////////
83 // Implementation of org.xml.sax.Attributes.
84 ////////////////////////////////////////////////////////////////////
88 * Return the number of attributes in the list.
90 * @return The number of attributes in the list.
91 * @see org.xml.sax.Attributes#getLength
93 public int getLength ()
100 * Return an attribute's Namespace URI.
102 * @param index The attribute's index (zero-based).
103 * @return The Namespace URI, the empty string if none is
104 * available, or null if the index is out of range.
105 * @see org.xml.sax.Attributes#getURI
107 public String
getURI (int index
)
109 if (index
>= 0 && index
< length
) {
110 return data
[index
*5];
118 * Return an attribute's local name.
120 * @param index The attribute's index (zero-based).
121 * @return The attribute's local name, the empty string if
122 * none is available, or null if the index if out of range.
123 * @see org.xml.sax.Attributes#getLocalName
125 public String
getLocalName (int index
)
127 if (index
>= 0 && index
< length
) {
128 return data
[index
*5+1];
136 * Return an attribute's qualified (prefixed) name.
138 * @param index The attribute's index (zero-based).
139 * @return The attribute's qualified name, the empty string if
140 * none is available, or null if the index is out of bounds.
141 * @see org.xml.sax.Attributes#getQName
143 public String
getQName (int index
)
145 if (index
>= 0 && index
< length
) {
146 return data
[index
*5+2];
154 * Return an attribute's type by index.
156 * @param index The attribute's index (zero-based).
157 * @return The attribute's type, "CDATA" if the type is unknown, or null
158 * if the index is out of bounds.
159 * @see org.xml.sax.Attributes#getType(int)
161 public String
getType (int index
)
163 if (index
>= 0 && index
< length
) {
164 return data
[index
*5+3];
172 * Return an attribute's value by index.
174 * @param index The attribute's index (zero-based).
175 * @return The attribute's value or null if the index is out of bounds.
176 * @see org.xml.sax.Attributes#getValue(int)
178 public String
getValue (int index
)
180 if (index
>= 0 && index
< length
) {
181 return data
[index
*5+4];
189 * Look up an attribute's index by Namespace name.
191 * <p>In many cases, it will be more efficient to look up the name once and
192 * use the index query methods rather than using the name query methods
195 * @param uri The attribute's Namespace URI, or the empty
196 * string if none is available.
197 * @param localName The attribute's local name.
198 * @return The attribute's index, or -1 if none matches.
199 * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
201 public int getIndex (String uri
, String localName
)
203 int max
= length
* 5;
204 for (int i
= 0; i
< max
; i
+= 5) {
205 if (data
[i
].equals(uri
) && data
[i
+1].equals(localName
)) {
214 * Look up an attribute's index by qualified (prefixed) name.
216 * @param qName The qualified name.
217 * @return The attribute's index, or -1 if none matches.
218 * @see org.xml.sax.Attributes#getIndex(java.lang.String)
220 public int getIndex (String qName
)
222 int max
= length
* 5;
223 for (int i
= 0; i
< max
; i
+= 5) {
224 if (data
[i
+2].equals(qName
)) {
233 * Look up an attribute's type by Namespace-qualified name.
235 * @param uri The Namespace URI, or the empty string for a name
236 * with no explicit Namespace URI.
237 * @param localName The local name.
238 * @return The attribute's type, or null if there is no
239 * matching attribute.
240 * @see org.xml.sax.Attributes#getType(java.lang.String,java.lang.String)
242 public String
getType (String uri
, String localName
)
244 int max
= length
* 5;
245 for (int i
= 0; i
< max
; i
+= 5) {
246 if (data
[i
].equals(uri
) && data
[i
+1].equals(localName
)) {
255 * Look up an attribute's type by qualified (prefixed) name.
257 * @param qName The qualified name.
258 * @return The attribute's type, or null if there is no
259 * matching attribute.
260 * @see org.xml.sax.Attributes#getType(java.lang.String)
262 public String
getType (String qName
)
264 int max
= length
* 5;
265 for (int i
= 0; i
< max
; i
+= 5) {
266 if (data
[i
+2].equals(qName
)) {
275 * Look up an attribute's value by Namespace-qualified name.
277 * @param uri The Namespace URI, or the empty string for a name
278 * with no explicit Namespace URI.
279 * @param localName The local name.
280 * @return The attribute's value, or null if there is no
281 * matching attribute.
282 * @see org.xml.sax.Attributes#getValue(java.lang.String,java.lang.String)
284 public String
getValue (String uri
, String localName
)
286 int max
= length
* 5;
287 for (int i
= 0; i
< max
; i
+= 5) {
288 if (data
[i
].equals(uri
) && data
[i
+1].equals(localName
)) {
297 * Look up an attribute's value by qualified (prefixed) name.
299 * @param qName The qualified name.
300 * @return The attribute's value, or null if there is no
301 * matching attribute.
302 * @see org.xml.sax.Attributes#getValue(java.lang.String)
304 public String
getValue (String qName
)
306 int max
= length
* 5;
307 for (int i
= 0; i
< max
; i
+= 5) {
308 if (data
[i
+2].equals(qName
)) {
317 ////////////////////////////////////////////////////////////////////
319 ////////////////////////////////////////////////////////////////////
323 * Clear the attribute list for reuse.
325 * <p>Note that little memory is freed by this call:
326 * the current array is kept so it can be
332 for (int i
= 0; i
< (length
* 5); i
++)
340 * Copy an entire Attributes object.
342 * <p>It may be more efficient to reuse an existing object
343 * rather than constantly allocating new ones.</p>
345 * @param atts The attributes to copy.
347 public void setAttributes (Attributes atts
)
350 length
= atts
.getLength();
352 data
= new String
[length
*5];
353 for (int i
= 0; i
< length
; i
++) {
354 data
[i
*5] = atts
.getURI(i
);
355 data
[i
*5+1] = atts
.getLocalName(i
);
356 data
[i
*5+2] = atts
.getQName(i
);
357 data
[i
*5+3] = atts
.getType(i
);
358 data
[i
*5+4] = atts
.getValue(i
);
365 * Add an attribute to the end of the list.
367 * <p>For the sake of speed, this method does no checking
368 * to see if the attribute is already in the list: that is
369 * the responsibility of the application.</p>
371 * @param uri The Namespace URI, or the empty string if
372 * none is available or Namespace processing is not
374 * @param localName The local name, or the empty string if
375 * Namespace processing is not being performed.
376 * @param qName The qualified (prefixed) name, or the empty string
377 * if qualified names are not available.
378 * @param type The attribute type as a string.
379 * @param value The attribute value.
381 public void addAttribute (String uri
, String localName
, String qName
,
382 String type
, String value
)
384 ensureCapacity(length
+1);
385 data
[length
*5] = uri
;
386 data
[length
*5+1] = localName
;
387 data
[length
*5+2] = qName
;
388 data
[length
*5+3] = type
;
389 data
[length
*5+4] = value
;
395 * Set an attribute in the list.
397 * <p>For the sake of speed, this method does no checking
398 * for name conflicts or well-formedness: such checks are the
399 * responsibility of the application.</p>
401 * @param index The index of the attribute (zero-based).
402 * @param uri The Namespace URI, or the empty string if
403 * none is available or Namespace processing is not
405 * @param localName The local name, or the empty string if
406 * Namespace processing is not being performed.
407 * @param qName The qualified name, or the empty string
408 * if qualified names are not available.
409 * @param type The attribute type as a string.
410 * @param value The attribute value.
411 * @exception java.lang.ArrayIndexOutOfBoundsException When the
412 * supplied index does not point to an attribute
415 public void setAttribute (int index
, String uri
, String localName
,
416 String qName
, String type
, String value
)
418 if (index
>= 0 && index
< length
) {
420 data
[index
*5+1] = localName
;
421 data
[index
*5+2] = qName
;
422 data
[index
*5+3] = type
;
423 data
[index
*5+4] = value
;
431 * Remove an attribute from the list.
433 * @param index The index of the attribute (zero-based).
434 * @exception java.lang.ArrayIndexOutOfBoundsException When the
435 * supplied index does not point to an attribute
438 public void removeAttribute (int index
)
440 if (index
>= 0 && index
< length
) {
441 if (index
< length
- 1) {
442 System
.arraycopy(data
, (index
+1)*5, data
, index
*5,
445 index
= (length
- 1) * 5;
446 data
[index
++] = null;
447 data
[index
++] = null;
448 data
[index
++] = null;
449 data
[index
++] = null;
459 * Set the Namespace URI of a specific attribute.
461 * @param index The index of the attribute (zero-based).
462 * @param uri The attribute's Namespace URI, or the empty
464 * @exception java.lang.ArrayIndexOutOfBoundsException When the
465 * supplied index does not point to an attribute
468 public void setURI (int index
, String uri
)
470 if (index
>= 0 && index
< length
) {
479 * Set the local name of a specific attribute.
481 * @param index The index of the attribute (zero-based).
482 * @param localName The attribute's local name, or the empty
484 * @exception java.lang.ArrayIndexOutOfBoundsException When the
485 * supplied index does not point to an attribute
488 public void setLocalName (int index
, String localName
)
490 if (index
>= 0 && index
< length
) {
491 data
[index
*5+1] = localName
;
499 * Set the qualified name of a specific attribute.
501 * @param index The index of the attribute (zero-based).
502 * @param qName The attribute's qualified name, or the empty
504 * @exception java.lang.ArrayIndexOutOfBoundsException When the
505 * supplied index does not point to an attribute
508 public void setQName (int index
, String qName
)
510 if (index
>= 0 && index
< length
) {
511 data
[index
*5+2] = qName
;
519 * Set the type of a specific attribute.
521 * @param index The index of the attribute (zero-based).
522 * @param type The attribute's type.
523 * @exception java.lang.ArrayIndexOutOfBoundsException When the
524 * supplied index does not point to an attribute
527 public void setType (int index
, String type
)
529 if (index
>= 0 && index
< length
) {
530 data
[index
*5+3] = type
;
538 * Set the value of a specific attribute.
540 * @param index The index of the attribute (zero-based).
541 * @param value The attribute's value.
542 * @exception java.lang.ArrayIndexOutOfBoundsException When the
543 * supplied index does not point to an attribute
546 public void setValue (int index
, String value
)
548 if (index
>= 0 && index
< length
) {
549 data
[index
*5+4] = value
;
557 ////////////////////////////////////////////////////////////////////
559 ////////////////////////////////////////////////////////////////////
563 * Ensure the internal array's capacity.
565 * @param n The minimum number of attributes that the array must
568 private void ensureCapacity (int n
) {
573 if (data
== null || data
.length
== 0) {
576 else if (data
.length
>= n
* 5) {
582 while (max
< n
* 5) {
586 String newData
[] = new String
[max
];
588 System
.arraycopy(data
, 0, newData
, 0, length
*5);
595 * Report a bad array index in a manipulator.
597 * @param index The index to report.
598 * @exception java.lang.ArrayIndexOutOfBoundsException Always.
600 private void badIndex (int index
)
601 throws ArrayIndexOutOfBoundsException
604 "Attempt to modify attribute at illegal index: " + index
;
605 throw new ArrayIndexOutOfBoundsException(msg
);
610 ////////////////////////////////////////////////////////////////////
612 ////////////////////////////////////////////////////////////////////
619 // end of AttributesImpl.java