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 2005/02/02 00:41:54 tromey Exp $
7 package org
.xml
.sax
.helpers
;
9 import org
.xml
.sax
.Attributes
;
13 * Default implementation of the Attributes interface.
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.
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
27 * <p>There are two typical uses of this class:</p>
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>
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>
43 * @author David Megginson
44 * @version 2.0.1 (sax2r2)
46 public class AttributesImpl
implements Attributes
50 ////////////////////////////////////////////////////////////////////
52 ////////////////////////////////////////////////////////////////////
56 * Construct a new, empty AttributesImpl object.
58 public AttributesImpl ()
66 * Copy an existing Attributes object.
68 * <p>This constructor is especially useful inside a
69 * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p>
71 * @param atts The existing Attributes object.
73 public AttributesImpl (Attributes atts
)
80 ////////////////////////////////////////////////////////////////////
81 // Implementation of org.xml.sax.Attributes.
82 ////////////////////////////////////////////////////////////////////
86 * Return the number of attributes in the list.
88 * @return The number of attributes in the list.
89 * @see org.xml.sax.Attributes#getLength
91 public int getLength ()
98 * Return an attribute's Namespace URI.
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
105 public String
getURI (int index
)
107 if (index
>= 0 && index
< length
) {
108 return data
[index
*5];
116 * Return an attribute's local name.
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
123 public String
getLocalName (int index
)
125 if (index
>= 0 && index
< length
) {
126 return data
[index
*5+1];
134 * Return an attribute's qualified (prefixed) name.
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
141 public String
getQName (int index
)
143 if (index
>= 0 && index
< length
) {
144 return data
[index
*5+2];
152 * Return an attribute's type by index.
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)
159 public String
getType (int index
)
161 if (index
>= 0 && index
< length
) {
162 return data
[index
*5+3];
170 * Return an attribute's value by index.
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)
176 public String
getValue (int index
)
178 if (index
>= 0 && index
< length
) {
179 return data
[index
*5+4];
187 * Look up an attribute's index by Namespace name.
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
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)
199 public int getIndex (String uri
, String localName
)
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
)) {
212 * Look up an attribute's index by qualified (prefixed) name.
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)
218 public int getIndex (String qName
)
220 int max
= length
* 5;
221 for (int i
= 0; i
< max
; i
+= 5) {
222 if (data
[i
+2].equals(qName
)) {
231 * Look up an attribute's type by Namespace-qualified name.
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)
240 public String
getType (String uri
, String localName
)
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
)) {
253 * Look up an attribute's type by qualified (prefixed) name.
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)
260 public String
getType (String qName
)
262 int max
= length
* 5;
263 for (int i
= 0; i
< max
; i
+= 5) {
264 if (data
[i
+2].equals(qName
)) {
273 * Look up an attribute's value by Namespace-qualified name.
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)
282 public String
getValue (String uri
, String localName
)
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
)) {
295 * Look up an attribute's value by qualified (prefixed) name.
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)
302 public String
getValue (String qName
)
304 int max
= length
* 5;
305 for (int i
= 0; i
< max
; i
+= 5) {
306 if (data
[i
+2].equals(qName
)) {
315 ////////////////////////////////////////////////////////////////////
317 ////////////////////////////////////////////////////////////////////
321 * Clear the attribute list for reuse.
323 * <p>Note that little memory is freed by this call:
324 * the current array is kept so it can be
330 for (int i
= 0; i
< (length
* 5); i
++)
338 * Copy an entire Attributes object.
340 * <p>It may be more efficient to reuse an existing object
341 * rather than constantly allocating new ones.</p>
343 * @param atts The attributes to copy.
345 public void setAttributes (Attributes atts
)
348 length
= atts
.getLength();
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
);
363 * Add an attribute to the end of the list.
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>
369 * @param uri The Namespace URI, or the empty string if
370 * none is available or Namespace processing is not
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.
379 public void addAttribute (String uri
, String localName
, String qName
,
380 String type
, String value
)
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
;
393 * Set an attribute in the list.
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>
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
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
413 public void setAttribute (int index
, String uri
, String localName
,
414 String qName
, String type
, String value
)
416 if (index
>= 0 && index
< length
) {
418 data
[index
*5+1] = localName
;
419 data
[index
*5+2] = qName
;
420 data
[index
*5+3] = type
;
421 data
[index
*5+4] = value
;
429 * Remove an attribute from the list.
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
436 public void removeAttribute (int index
)
438 if (index
>= 0 && index
< length
) {
439 if (index
< length
- 1) {
440 System
.arraycopy(data
, (index
+1)*5, data
, index
*5,
443 index
= (length
- 1) * 5;
444 data
[index
++] = null;
445 data
[index
++] = null;
446 data
[index
++] = null;
447 data
[index
++] = null;
457 * Set the Namespace URI of a specific attribute.
459 * @param index The index of the attribute (zero-based).
460 * @param uri The attribute's Namespace URI, or the empty
462 * @exception java.lang.ArrayIndexOutOfBoundsException When the
463 * supplied index does not point to an attribute
466 public void setURI (int index
, String uri
)
468 if (index
>= 0 && index
< length
) {
477 * Set the local name of a specific attribute.
479 * @param index The index of the attribute (zero-based).
480 * @param localName The attribute's local name, or the empty
482 * @exception java.lang.ArrayIndexOutOfBoundsException When the
483 * supplied index does not point to an attribute
486 public void setLocalName (int index
, String localName
)
488 if (index
>= 0 && index
< length
) {
489 data
[index
*5+1] = localName
;
497 * Set the qualified name of a specific attribute.
499 * @param index The index of the attribute (zero-based).
500 * @param qName The attribute's qualified name, or the empty
502 * @exception java.lang.ArrayIndexOutOfBoundsException When the
503 * supplied index does not point to an attribute
506 public void setQName (int index
, String qName
)
508 if (index
>= 0 && index
< length
) {
509 data
[index
*5+2] = qName
;
517 * Set the type of a specific attribute.
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
525 public void setType (int index
, String type
)
527 if (index
>= 0 && index
< length
) {
528 data
[index
*5+3] = type
;
536 * Set the value of a specific attribute.
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
544 public void setValue (int index
, String value
)
546 if (index
>= 0 && index
< length
) {
547 data
[index
*5+4] = value
;
555 ////////////////////////////////////////////////////////////////////
557 ////////////////////////////////////////////////////////////////////
561 * Ensure the internal array's capacity.
563 * @param n The minimum number of attributes that the array must
566 private void ensureCapacity (int n
) {
571 if (data
== null || data
.length
== 0) {
574 else if (data
.length
>= n
* 5) {
580 while (max
< n
* 5) {
584 String newData
[] = new String
[max
];
586 System
.arraycopy(data
, 0, newData
, 0, length
*5);
593 * Report a bad array index in a manipulator.
595 * @param index The index to report.
596 * @exception java.lang.ArrayIndexOutOfBoundsException Always.
598 private void badIndex (int index
)
599 throws ArrayIndexOutOfBoundsException
602 "Attempt to modify attribute at illegal index: " + index
;
603 throw new ArrayIndexOutOfBoundsException(msg
);
608 ////////////////////////////////////////////////////////////////////
610 ////////////////////////////////////////////////////////////////////
617 // end of AttributesImpl.java