View Javadoc

1   // Attributes2Impl.java - extended AttributesImpl
2   // http://www.saxproject.org
3   // Public Domain: no warranty.
4   // $Id: Attributes2Impl.java,v 1.4 2004/03/19 20:17:54 maartenc Exp $
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 }