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