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