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