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