1. // Attributes2Impl.java - extended AttributesImpl
  2. // http://www.saxproject.org
  3. // Public Domain: no warranty.
  4. // $Id: Attributes2Impl.java,v 1.1.2.1 2004/05/01 08:34:43 jsuttor Exp $
  5. package org.xml.sax.ext;
  6. import org.xml.sax.Attributes;
  7. import org.xml.sax.helpers.AttributesImpl;
  8. /**
  9. * SAX2 extension helper for additional Attributes information,
  10. * implementing the {@link Attributes2} interface.
  11. *
  12. * <blockquote>
  13. * <em>This module, both source code and documentation, is in the
  14. * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
  15. * </blockquote>
  16. *
  17. * <p>This is not part of core-only SAX2 distributions.</p>
  18. *
  19. * <p>The <em>specified</em> flag for each attribute will always
  20. * be true, unless it has been set to false in the copy constructor
  21. * or using {@link #setSpecified}.
  22. * Similarly, the <em>declared</em> flag for each attribute will
  23. * always be false, except for defaulted attributes (<em>specified</em>
  24. * is false), non-CDATA attributes, or when it is set to true using
  25. * {@link #setDeclared}.
  26. * If you change an attribute's type by hand, you may need to modify
  27. * its <em>declared</em> flag to match.
  28. * </p>
  29. *
  30. * @since SAX 2.0 (extensions 1.1 alpha)
  31. * @author David Brownell
  32. * @version TBS
  33. */
  34. public class Attributes2Impl extends AttributesImpl implements Attributes2
  35. {
  36. private boolean declared [];
  37. private boolean specified [];
  38. /**
  39. * Construct a new, empty Attributes2Impl object.
  40. */
  41. public Attributes2Impl () { }
  42. /**
  43. * Copy an existing Attributes or Attributes2 object.
  44. * If the object implements Attributes2, values of the
  45. * <em>specified</em> and <em>declared</em> flags for each
  46. * attribute are copied.
  47. * Otherwise the flag values are defaulted to assume no DTD was used,
  48. * unless there is evidence to the contrary (such as attributes with
  49. * type other than CDATA, which must have been <em>declared</em>).
  50. *
  51. * <p>This constructor is especially useful inside a
  52. * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p>
  53. *
  54. * @param atts The existing Attributes object.
  55. */
  56. public Attributes2Impl (Attributes atts)
  57. {
  58. super (atts);
  59. }
  60. ////////////////////////////////////////////////////////////////////
  61. // Implementation of Attributes2
  62. ////////////////////////////////////////////////////////////////////
  63. /**
  64. * Returns the current value of the attribute's "declared" flag.
  65. */
  66. // javadoc mostly from interface
  67. public boolean isDeclared (int index)
  68. {
  69. if (index < 0 || index >= getLength ())
  70. throw new ArrayIndexOutOfBoundsException (
  71. "No attribute at index: " + index);
  72. return declared [index];
  73. }
  74. /**
  75. * Returns the current value of the attribute's "declared" flag.
  76. */
  77. // javadoc mostly from interface
  78. public boolean isDeclared (String uri, String localName)
  79. {
  80. int index = getIndex (uri, localName);
  81. if (index < 0)
  82. throw new IllegalArgumentException (
  83. "No such attribute: local=" + localName
  84. + ", namespace=" + uri);
  85. return declared [index];
  86. }
  87. /**
  88. * Returns the current value of the attribute's "declared" flag.
  89. */
  90. // javadoc mostly from interface
  91. public boolean isDeclared (String qName)
  92. {
  93. int index = getIndex (qName);
  94. if (index < 0)
  95. throw new IllegalArgumentException (
  96. "No such attribute: " + qName);
  97. return declared [index];
  98. }
  99. /**
  100. * Returns the current value of an attribute's "specified" flag.
  101. *
  102. * @param index The attribute index (zero-based).
  103. * @return current flag value
  104. * @exception java.lang.ArrayIndexOutOfBoundsException When the
  105. * supplied index does not identify an attribute.
  106. */
  107. public boolean isSpecified (int index)
  108. {
  109. if (index < 0 || index >= getLength ())
  110. throw new ArrayIndexOutOfBoundsException (
  111. "No attribute at index: " + index);
  112. return specified [index];
  113. }
  114. /**
  115. * Returns the current value of an attribute's "specified" flag.
  116. *
  117. * @param uri The Namespace URI, or the empty string if
  118. * the name has no Namespace URI.
  119. * @param localName The attribute's local name.
  120. * @return current flag value
  121. * @exception java.lang.IllegalArgumentException When the
  122. * supplied names do not identify an attribute.
  123. */
  124. public boolean isSpecified (String uri, String localName)
  125. {
  126. int index = getIndex (uri, localName);
  127. if (index < 0)
  128. throw new IllegalArgumentException (
  129. "No such attribute: local=" + localName
  130. + ", namespace=" + uri);
  131. return specified [index];
  132. }
  133. /**
  134. * Returns the current value of an attribute's "specified" flag.
  135. *
  136. * @param qName The XML qualified (prefixed) name.
  137. * @return current flag value
  138. * @exception java.lang.IllegalArgumentException When the
  139. * supplied name does not identify an attribute.
  140. */
  141. public boolean isSpecified (String qName)
  142. {
  143. int index = getIndex (qName);
  144. if (index < 0)
  145. throw new IllegalArgumentException (
  146. "No such attribute: " + qName);
  147. return specified [index];
  148. }
  149. ////////////////////////////////////////////////////////////////////
  150. // Manipulators
  151. ////////////////////////////////////////////////////////////////////
  152. /**
  153. * Copy an entire Attributes object. The "specified" flags are
  154. * assigned as true, and "declared" flags as false (except when
  155. * an attribute's type is not CDATA),
  156. * unless the object is an Attributes2 object.
  157. * In that case those flag values are all copied.
  158. *
  159. * @see AttributesImpl#setAttributes
  160. */
  161. public void setAttributes (Attributes atts)
  162. {
  163. int length = atts.getLength ();
  164. super.setAttributes (atts);
  165. declared = new boolean [length];
  166. specified = new boolean [length];
  167. if (atts instanceof Attributes2) {
  168. Attributes2 a2 = (Attributes2) atts;
  169. for (int i = 0; i < length; i++) {
  170. declared [i] = a2.isDeclared (i);
  171. specified [i] = a2.isSpecified (i);
  172. }
  173. } else {
  174. for (int i = 0; i < length; i++) {
  175. declared [i] = !"CDATA".equals (atts.getType (i));
  176. specified [i] = true;
  177. }
  178. }
  179. }
  180. /**
  181. * Add an attribute to the end of the list, setting its
  182. * "specified" flag to true. To set that flag's value
  183. * to false, use {@link #setSpecified}.
  184. *
  185. * <p>Unless the attribute <em>type</em> is CDATA, this attribute
  186. * is marked as being declared in the DTD. To set that flag's value
  187. * to true for CDATA attributes, use {@link #setDeclared}.
  188. *
  189. * @see AttributesImpl#addAttribute
  190. */
  191. public void addAttribute (String uri, String localName, String qName,
  192. String type, String value)
  193. {
  194. super.addAttribute (uri, localName, qName, type, value);
  195. int length = getLength ();
  196. if (length < specified.length) {
  197. boolean newFlags [];
  198. newFlags = new boolean [length];
  199. System.arraycopy (declared, 0, newFlags, 0, declared.length);
  200. declared = newFlags;
  201. newFlags = new boolean [length];
  202. System.arraycopy (specified, 0, newFlags, 0, specified.length);
  203. specified = newFlags;
  204. }
  205. specified [length - 1] = true;
  206. declared [length - 1] = !"CDATA".equals (type);
  207. }
  208. // javadoc entirely from superclass
  209. public void removeAttribute (int index)
  210. {
  211. int origMax = getLength () - 1;
  212. super.removeAttribute (index);
  213. if (index != origMax) {
  214. System.arraycopy (declared, index + 1, declared, index,
  215. origMax - index);
  216. System.arraycopy (specified, index + 1, specified, index,
  217. origMax - index);
  218. }
  219. }
  220. /**
  221. * Assign a value to the "declared" flag of a specific attribute.
  222. * This is normally needed only for attributes of type CDATA,
  223. * including attributes whose type is changed to or from CDATA.
  224. *
  225. * @param index The index of the attribute (zero-based).
  226. * @param value The desired flag value.
  227. * @exception java.lang.ArrayIndexOutOfBoundsException When the
  228. * supplied index does not identify an attribute.
  229. * @see #setType
  230. */
  231. public void setDeclared (int index, boolean value)
  232. {
  233. if (index < 0 || index >= getLength ())
  234. throw new ArrayIndexOutOfBoundsException (
  235. "No attribute at index: " + index);
  236. declared [index] = value;
  237. }
  238. /**
  239. * Assign a value to the "specified" flag of a specific attribute.
  240. * This is the only way this flag can be cleared, except clearing
  241. * by initialization with the copy constructor.
  242. *
  243. * @param index The index of the attribute (zero-based).
  244. * @param value The desired flag value.
  245. * @exception java.lang.ArrayIndexOutOfBoundsException When the
  246. * supplied index does not identify an attribute.
  247. */
  248. public void setSpecified (int index, boolean value)
  249. {
  250. if (index < 0 || index >= getLength ())
  251. throw new ArrayIndexOutOfBoundsException (
  252. "No attribute at index: " + index);
  253. specified [index] = value;
  254. }
  255. }