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