1 // Attributes2Impl.java - extended AttributesImpl
2 // http://www.saxproject.org
3 // Public Domain: no warranty.
4 // $Id: Attributes2Impl.java,v 1.5 2004/03/08 13:01:01 dmegginson Exp $
5 
6 package org.xml.sax.ext;
7 
8 import libcore.util.EmptyArray;
9 import org.xml.sax.Attributes;
10 import org.xml.sax.helpers.AttributesImpl;
11 
12 /**
13  * SAX2 extension helper for additional Attributes information,
14  * implementing the {@link Attributes2} interface.
15  *
16  * <blockquote>
17  * <em>This module, both source code and documentation, is in the
18  * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
19  * </blockquote>
20  *
21  * <p>This is not part of core-only SAX2 distributions.</p>
22  *
23  * <p>The <em>specified</em> flag for each attribute will always
24  * be true, unless it has been set to false in the copy constructor
25  * or using {@link #setSpecified}.
26  * Similarly, the <em>declared</em> flag for each attribute will
27  * always be false, except for defaulted attributes (<em>specified</em>
28  * is false), non-CDATA attributes, or when it is set to true using
29  * {@link #setDeclared}.
30  * If you change an attribute's type by hand, you may need to modify
31  * its <em>declared</em> flag to match.
32  * </p>
33  *
34  * @since SAX 2.0 (extensions 1.1 alpha)
35  * @author David Brownell
36  * @version TBS
37  */
38 public class Attributes2Impl extends AttributesImpl implements Attributes2
39 {
40     private boolean[] declared;
41     private boolean[] specified;
42 
43 
44     /**
45      * Construct a new, empty Attributes2Impl object.
46      */
Attributes2Impl()47     public Attributes2Impl () {
48         declared = EmptyArray.BOOLEAN;
49         specified = EmptyArray.BOOLEAN;
50     }
51 
52 
53     /**
54      * Copy an existing Attributes or Attributes2 object.
55      * If the object implements Attributes2, values of the
56      * <em>specified</em> and <em>declared</em> flags for each
57      * attribute are copied.
58      * Otherwise the flag values are defaulted to assume no DTD was used,
59      * unless there is evidence to the contrary (such as attributes with
60      * type other than CDATA, which must have been <em>declared</em>).
61      *
62      * <p>This constructor is especially useful inside a
63      * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p>
64      *
65      * @param atts The existing Attributes object.
66      */
Attributes2Impl(Attributes atts)67     public Attributes2Impl (Attributes atts)
68     {
69     super (atts);
70     }
71 
72 
73     ////////////////////////////////////////////////////////////////////
74     // Implementation of Attributes2
75     ////////////////////////////////////////////////////////////////////
76 
77 
78     /*
79      * Returns the current value of the attribute's "declared" flag.
80      */
81     // javadoc mostly from interface
isDeclared(int index)82     public boolean isDeclared (int index)
83     {
84     if (index < 0 || index >= getLength ())
85         throw new ArrayIndexOutOfBoundsException (
86         "No attribute at index: " + index);
87     return declared [index];
88     }
89 
90 
91     /*
92      * Returns the current value of the attribute's "declared" flag.
93      */
94     // javadoc mostly from interface
isDeclared(String uri, String localName)95     public boolean isDeclared (String uri, String localName)
96     {
97     int index = getIndex (uri, localName);
98 
99     if (index < 0)
100         throw new IllegalArgumentException (
101         "No such attribute: local=" + localName
102         + ", namespace=" + uri);
103     return declared [index];
104     }
105 
106 
107     /*
108      * Returns the current value of the attribute's "declared" flag.
109      */
110     // javadoc mostly from interface
isDeclared(String qName)111     public boolean isDeclared (String qName)
112     {
113     int index = getIndex (qName);
114 
115     if (index < 0)
116         throw new IllegalArgumentException (
117         "No such attribute: " + qName);
118     return declared [index];
119     }
120 
121 
122     /**
123      * Returns the current value of an attribute's "specified" flag.
124      *
125      * @param index The attribute index (zero-based).
126      * @return current flag value
127      * @exception java.lang.ArrayIndexOutOfBoundsException When the
128      *            supplied index does not identify an attribute.
129      */
isSpecified(int index)130     public boolean isSpecified (int index)
131     {
132     if (index < 0 || index >= getLength ())
133         throw new ArrayIndexOutOfBoundsException (
134         "No attribute at index: " + index);
135     return specified [index];
136     }
137 
138 
139     /**
140      * Returns the current value of an attribute's "specified" flag.
141      *
142      * @param uri The Namespace URI, or the empty string if
143      *        the name has no Namespace URI.
144      * @param localName The attribute's local name.
145      * @return current flag value
146      * @exception java.lang.IllegalArgumentException When the
147      *            supplied names do not identify an attribute.
148      */
isSpecified(String uri, String localName)149     public boolean isSpecified (String uri, String localName)
150     {
151     int index = getIndex (uri, localName);
152 
153     if (index < 0)
154         throw new IllegalArgumentException (
155         "No such attribute: local=" + localName
156         + ", namespace=" + uri);
157     return specified [index];
158     }
159 
160 
161     /**
162      * Returns the current value of an attribute's "specified" flag.
163      *
164      * @param qName The XML qualified (prefixed) name.
165      * @return current flag value
166      * @exception java.lang.IllegalArgumentException When the
167      *            supplied name does not identify an attribute.
168      */
isSpecified(String qName)169     public boolean isSpecified (String qName)
170     {
171     int index = getIndex (qName);
172 
173     if (index < 0)
174         throw new IllegalArgumentException (
175         "No such attribute: " + qName);
176     return specified [index];
177     }
178 
179 
180     ////////////////////////////////////////////////////////////////////
181     // Manipulators
182     ////////////////////////////////////////////////////////////////////
183 
184 
185     /**
186      * Copy an entire Attributes object.  The "specified" flags are
187      * assigned as true, and "declared" flags as false (except when
188      * an attribute's type is not CDATA),
189      * unless the object is an Attributes2 object.
190      * In that case those flag values are all copied.
191      *
192      * @param atts The attributes to copy.
193      *
194      * @see AttributesImpl#setAttributes
195      */
setAttributes(Attributes atts)196     public void setAttributes (Attributes atts)
197     {
198     int length = atts.getLength ();
199 
200     super.setAttributes (atts);
201     declared = new boolean [length];
202     specified = new boolean [length];
203 
204     if (atts instanceof Attributes2) {
205         Attributes2    a2 = (Attributes2) atts;
206         for (int i = 0; i < length; i++) {
207         declared [i] = a2.isDeclared (i);
208         specified [i] = a2.isSpecified (i);
209         }
210     } else {
211         for (int i = 0; i < length; i++) {
212         declared [i] = !"CDATA".equals (atts.getType (i));
213         specified [i] = true;
214         }
215     }
216     }
217 
218 
219     /**
220      * Add an attribute to the end of the list, setting its
221      * "specified" flag to true.  To set that flag's value
222      * to false, use {@link #setSpecified}.
223      *
224      * <p>Unless the attribute <em>type</em> is CDATA, this attribute
225      * is marked as being declared in the DTD.  To set that flag's value
226      * to true for CDATA attributes, use {@link #setDeclared}.
227      *
228      * @param uri The Namespace URI, or the empty string if
229      *        none is available or Namespace processing is not
230      *        being performed.
231      * @param localName The local name, or the empty string if
232      *        Namespace processing is not being performed.
233      * @param qName The qualified (prefixed) name, or the empty string
234      *        if qualified names are not available.
235      * @param type The attribute type as a string.
236      * @param value The attribute value.
237      *
238      * @see AttributesImpl#addAttribute
239      */
addAttribute(String uri, String localName, String qName, String type, String value)240     public void addAttribute (String uri, String localName, String qName,
241                   String type, String value)
242     {
243     super.addAttribute (uri, localName, qName, type, value);
244 
245     int length = getLength ();
246 
247     if (length > specified.length) {
248         boolean[] newFlags = new boolean [length];
249         System.arraycopy (declared, 0, newFlags, 0, declared.length);
250         declared = newFlags;
251 
252         newFlags = new boolean [length];
253         System.arraycopy (specified, 0, newFlags, 0, specified.length);
254         specified = newFlags;
255     }
256 
257     specified [length - 1] = true;
258     declared [length - 1] = !"CDATA".equals (type);
259     }
260 
261 
262     // javadoc entirely from superclass
removeAttribute(int index)263     public void removeAttribute (int index)
264     {
265     int origMax = getLength () - 1;
266 
267     super.removeAttribute (index);
268     if (index != origMax) {
269         System.arraycopy (declared, index + 1, declared, index,
270             origMax - index);
271         System.arraycopy (specified, index + 1, specified, index,
272             origMax - index);
273     }
274     }
275 
276 
277     /**
278      * Assign a value to the "declared" flag of a specific attribute.
279      * This is normally needed only for attributes of type CDATA,
280      * including attributes whose type is changed to or from CDATA.
281      *
282      * @param index The index of the attribute (zero-based).
283      * @param value The desired flag value.
284      * @exception java.lang.ArrayIndexOutOfBoundsException When the
285      *            supplied index does not identify an attribute.
286      * @see #setType
287      */
setDeclared(int index, boolean value)288     public void setDeclared (int index, boolean value)
289     {
290     if (index < 0 || index >= getLength ())
291         throw new ArrayIndexOutOfBoundsException (
292         "No attribute at index: " + index);
293     declared [index] = value;
294     }
295 
296 
297     /**
298      * Assign a value to the "specified" flag of a specific attribute.
299      * This is the only way this flag can be cleared, except clearing
300      * by initialization with the copy constructor.
301      *
302      * @param index The index of the attribute (zero-based).
303      * @param value The desired flag value.
304      * @exception java.lang.ArrayIndexOutOfBoundsException When the
305      *            supplied index does not identify an attribute.
306      */
setSpecified(int index, boolean value)307     public void setSpecified (int index, boolean value)
308     {
309     if (index < 0 || index >= getLength ())
310         throw new ArrayIndexOutOfBoundsException (
311         "No attribute at index: " + index);
312     specified [index] = value;
313     }
314 }
315