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