KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jdom > AttributeList


1 /*--
2
3  $Id: AttributeList.java,v 1.23 2004/02/28 03:30:27 jhunter Exp $
4
5  Copyright (C) 2000-2004 Jason Hunter & Brett McLaughlin.
6  All rights reserved.
7
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions
10  are met:
11
12  1. Redistributions of source code must retain the above copyright
13     notice, this list of conditions, and the following disclaimer.
14
15  2. Redistributions in binary form must reproduce the above copyright
16     notice, this list of conditions, and the disclaimer that follows
17     these conditions in the documentation and/or other materials
18     provided with the distribution.
19
20  3. The name "JDOM" must not be used to endorse or promote products
21     derived from this software without prior written permission. For
22     written permission, please contact <request_AT_jdom_DOT_org>.
23
24  4. Products derived from this software may not be called "JDOM", nor
25     may "JDOM" appear in their name, without prior written permission
26     from the JDOM Project Management <request_AT_jdom_DOT_org>.
27
28  In addition, we request (but do not require) that you include in the
29  end-user documentation provided with the redistribution and/or in the
30  software itself an acknowledgement equivalent to the following:
31      "This product includes software developed by the
32       JDOM Project (http://www.jdom.org/)."
33  Alternatively, the acknowledgment may be graphical using the logos
34  available at http://www.jdom.org/images/logos.
35
36  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
40  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  SUCH DAMAGE.
48
49  This software consists of voluntary contributions made by many
50  individuals on behalf of the JDOM Project and was originally
51  created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
52  Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information
53  on the JDOM Project, please see <http://www.jdom.org/>.
54
55  */

56
57 package org.jdom;
58
59 import java.util.*;
60
61 /**
62  * <code>AttributeList</code> represents legal JDOM <code>Attribute</code>
63  * content. This class is NOT PUBLIC; users should see it as a simple List
64  * implementation.
65  *
66  * @author Alex Rosen
67  * @author Philippe Riand
68  * @author Bradley S. Huffman
69  * @version $Revision: 1.23 $, $Date: 2004/02/28 03:30:27 $
70  * @see CDATA
71  * @see Comment
72  * @see Element
73  * @see EntityRef
74  * @see ProcessingInstruction
75  * @see Text
76  */

77 class AttributeList extends AbstractList
78                     implements List, java.io.Serializable JavaDoc {
79
80     private static final String JavaDoc CVS_ID =
81       "@(#) $RCSfile: AttributeList.java,v $ $Revision: 1.23 $ $Date: 2004/02/28 03:30:27 $ $Name: $";
82
83     private static final int INITIAL_ARRAY_SIZE = 5;
84
85     /** The backing list */
86     private Attribute elementData[];
87     private int size;
88
89     /** The parent Element */
90     private Element parent;
91
92     /** Force an Element parent */
93     private AttributeList() {}
94
95     /**
96      * Create a new instance of the AttributeList representing
97      * Element content
98      *
99      * @param parent element whose attributes are to be held
100      */

101     AttributeList(Element parent) {
102         this.parent = parent;
103     }
104
105     /**
106      * Package internal method to support building from sources that are
107      * 100% trusted.
108      *
109      * @param a attribute to add without any checks
110      */

111     final void uncheckedAddAttribute(Attribute a) {
112         a.parent = parent;
113         ensureCapacity(size + 1);
114         elementData[size++] = a;
115         modCount++;
116     }
117
118     /**
119      * Add a attribute to the end of the list or replace a existing
120      * attribute with the same name and <code>Namespace</code>.
121      *
122      * @param obj The object to insert into the list.
123      * @return true (as per the general contract of Collection.add).
124      * @throws IndexOutOfBoundsException if index < 0 || index > size()
125      */

126     public boolean add(Object JavaDoc obj) {
127         if (obj instanceof Attribute) {
128             Attribute attribute = (Attribute) obj;
129             int duplicate = indexOfDuplicate(attribute);
130             if (duplicate < 0) {
131                 add(size(), attribute);
132             }
133             else {
134                 set(duplicate, attribute);
135             }
136         }
137         else if (obj == null) {
138             throw new IllegalAddException("Cannot add null attribute");
139         }
140         else {
141             throw new IllegalAddException("Class " +
142                                           obj.getClass().getName() +
143                                           " is not an attribute");
144         }
145         return true;
146     }
147
148     /**
149      * Inserts the specified attribute at the specified position in this list.
150      * Shifts the attribute currently at that position (if any) and any
151      * subsequent attributes to the right (adds one to their indices).
152      *
153      * @param index The location to set the value to.
154      * @param obj The object to insert into the list.
155      * throws IndexOutOfBoundsException if index < 0 || index > size()
156      */

157     public void add(int index, Object JavaDoc obj) {
158         if (obj instanceof Attribute) {
159             Attribute attribute = (Attribute) obj;
160             int duplicate = indexOfDuplicate(attribute);
161             if (duplicate >= 0) {
162                 throw new IllegalAddException("Cannot add duplicate attribute");
163             }
164             add(index, attribute);
165         }
166         else if (obj == null) {
167             throw new IllegalAddException("Cannot add null attribute");
168         }
169         else {
170             throw new IllegalAddException("Class " +
171                                           obj.getClass().getName() +
172                                           " is not an attribute");
173         }
174         modCount++;
175     }
176
177     /**
178      * Check and add the <code>Attribute</code> to this list at
179      * the given index. Note: does not check for duplicate
180      * attributes.
181      *
182      * @param index index where to add <code>Attribute</code>
183      * @param attribute <code>Attribute</code> to add
184      */

185     void add(int index, Attribute attribute) {
186         if (attribute.getParent() != null) {
187             throw new IllegalAddException(
188                           "The attribute already has an existing parent \"" +
189                           attribute.getParent().getQualifiedName() + "\"");
190         }
191
192         String JavaDoc reason = Verifier.checkNamespaceCollision(attribute, parent);
193         if (reason != null) {
194             throw new IllegalAddException(parent, attribute, reason);
195         }
196
197         if (index<0 || index>size) {
198             throw new IndexOutOfBoundsException JavaDoc("Index: " + index +
199                                                 " Size: " + size());
200         }
201
202         attribute.setParent(parent);
203
204         ensureCapacity(size+1);
205         if( index==size ) {
206             elementData[size++] = attribute;
207         } else {
208             System.arraycopy(elementData, index, elementData, index + 1, size - index);
209             elementData[index] = attribute;
210             size++;
211         }
212         modCount++;
213     }
214
215     /**
216      * Add all the objects in the specified collection.
217      *
218      * @param collection The collection containing all the objects to add.
219      * @return <code>true</code> if the list was modified as a result of
220      * the add.
221      */

222     public boolean addAll(Collection collection) {
223         return addAll(size(), collection);
224     }
225
226     /**
227      * Inserts the specified collecton at the specified position in this list.
228      * Shifts the attribute currently at that position (if any) and any
229      * subsequent attributes to the right (adds one to their indices).
230      *
231      * @param index The offset to start adding the data in the collection
232      * @param collection The collection to insert into the list.
233      * @return <code>true</code> if the list was modified as a result of
234      * the add.
235      * throws IndexOutOfBoundsException if index < 0 || index > size()
236      */

237     public boolean addAll(int index, Collection collection) {
238         if (index<0 || index>size) {
239             throw new IndexOutOfBoundsException JavaDoc("Index: " + index +
240                                                 " Size: " + size());
241         }
242
243         if ((collection == null) || (collection.size() == 0)) {
244             return false;
245         }
246         ensureCapacity(size() + collection.size());
247
248         int count = 0;
249
250         try {
251             Iterator i = collection.iterator();
252             while (i.hasNext()) {
253                 Object JavaDoc obj = i.next();
254                 add(index + count, obj);
255                 count++;
256             }
257         }
258         catch (RuntimeException JavaDoc exception) {
259             for (int i = 0; i < count; i++) {
260                 remove(index);
261             }
262             throw exception;
263         }
264
265         return true;
266     }
267
268     /**
269      * Clear the current list.
270      */

271     public void clear() {
272         if (elementData != null) {
273             for (int i = 0; i < size; i++) {
274                 Attribute attribute = elementData[i];
275                 attribute.setParent(null);
276             }
277             elementData = null;
278             size = 0;
279         }
280         modCount++;
281     }
282
283     /**
284      * Clear the current list and set it to the contents
285      * of the <code>Collection</code>.
286      * object.
287      *
288      * @param collection The collection to use.
289      */

290     void clearAndSet(Collection collection) {
291         Attribute[] old = elementData;
292         int oldSize = size;
293
294         elementData = null;
295         size = 0;
296
297         if ((collection != null) && (collection.size() != 0)) {
298             ensureCapacity(collection.size());
299             try {
300                 addAll(0, collection);
301             }
302             catch (RuntimeException JavaDoc exception) {
303                 elementData = old;
304                 size = oldSize;
305                 throw exception;
306             }
307         }
308
309         if (old != null) {
310             for (int i = 0; i < oldSize; i++) {
311                 Attribute attribute = old[i];
312                 attribute.setParent(null);
313             }
314         }
315         modCount++;
316     }
317
318     /**
319      * Increases the capacity of this <code>AttributeList</code> instance,
320      * if necessary, to ensure that it can hold at least the number of
321      * items specified by the minimum capacity argument.
322      *
323      * @param minCapacity the desired minimum capacity.
324      */

325     private void ensureCapacity(int minCapacity) {
326         if (elementData == null) {
327             elementData = new Attribute[Math.max(minCapacity, INITIAL_ARRAY_SIZE)];
328         }
329         else {
330             int oldCapacity = elementData.length;
331             if (minCapacity > oldCapacity) {
332                 Attribute oldData[] = elementData;
333                 int newCapacity = (oldCapacity * 3)/2 + 1;
334                 if (newCapacity < minCapacity)
335                     newCapacity = minCapacity;
336                 elementData = new Attribute[newCapacity];
337                 System.arraycopy(oldData, 0, elementData, 0, size);
338             }
339         }
340     }
341
342     /**
343      * Return the object at the specified offset.
344      *
345      * @param index The offset of the object.
346      * @return The Object which was returned.
347      */

348     public Object JavaDoc get(int index) {
349         if (index<0 || index>=size) {
350             throw new IndexOutOfBoundsException JavaDoc("Index: " + index +
351                                                 " Size: " + size());
352         }
353
354         return elementData[index];
355     }
356
357     /**
358      * Return the <code>Attribute</code> with the
359      * given name and <code>Namespace</code>.
360      *
361      * @param name name of attribute to return
362      * @param namespace <code>Namespace</code> to match
363      * @return the <code>Attribute</code>, or null if one doesn't exist.
364      */

365     Object JavaDoc get(String JavaDoc name, Namespace namespace) {
366         int index = indexOf(name, namespace);
367         if (index < 0) {
368             return null;
369         }
370         return elementData[index];
371     }
372
373     /**
374      * Return index of the <code>Attribute</code> with the
375      * given name and uri.
376      */

377     int indexOf(String JavaDoc name, Namespace namespace) {
378         String JavaDoc uri = namespace.getURI();
379         if (elementData != null) {
380             for (int i = 0; i < size; i++) {
381                 Attribute old = elementData[i];
382                 String JavaDoc oldURI = old.getNamespaceURI();
383                 String JavaDoc oldName = old.getName();
384                 if (oldURI.equals(uri) && oldName.equals(name)) {
385                     return i;
386                 }
387             }
388         }
389         return -1;
390     }
391
392     /**
393      * Remove the object at the specified offset.
394      *
395      * @param index The offset of the object.
396      * @return The Object which was removed.
397      */

398     public Object JavaDoc remove(int index) {
399         if (index<0 || index>=size)
400             throw new IndexOutOfBoundsException JavaDoc("Index: " + index +
401                                                 " Size: " + size());
402
403         Attribute old = elementData[index];
404         old.setParent(null);
405         int numMoved = size - index - 1;
406         if (numMoved > 0)
407             System.arraycopy(elementData, index+1, elementData, index,numMoved);
408         elementData[--size] = null; // Let gc do its work
409
modCount++;
410         return old;
411     }
412
413     /**
414      * Remove the <code>Attribute</code> with the
415      * given name and <code>Namespace</code>.
416      *
417      * @param namespace <code>Namespace</code> to match
418      * @return the <code>true</code> if attribute was removed,
419      * <code>false</code> otherwise
420      */

421     boolean remove(String JavaDoc name, Namespace namespace) {
422         int index = indexOf(name, namespace);
423         if (index < 0) {
424             return false;
425         }
426         remove(index);
427         return true;
428     }
429
430     /**
431      * Set the object at the specified location to the supplied
432      * object.
433      *
434      * @param index The location to set the value to.
435      * @param obj The location to set the value to.
436      * @return The object which was replaced.
437      * throws IndexOutOfBoundsException if index < 0 || index >= size()
438      */

439     public Object JavaDoc set(int index, Object JavaDoc obj) {
440         if (obj instanceof Attribute) {
441             Attribute attribute = (Attribute) obj;
442             int duplicate = indexOfDuplicate(attribute);
443             if ((duplicate >= 0) && (duplicate != index)) {
444                 throw new IllegalAddException("Cannot set duplicate attribute");
445             }
446             return set(index, attribute);
447         }
448         else if (obj == null) {
449             throw new IllegalAddException("Cannot add null attribute");
450         }
451         else {
452             throw new IllegalAddException("Class " +
453                                           obj.getClass().getName() +
454                                           " is not an attribute");
455         }
456     }
457
458     /**
459      * Set the object at the specified location to the supplied
460      * object. Note: does not check for duplicate attributes.
461      *
462      * @param index The location to set the value to.
463      * @param attribute The attribute to set.
464      * @return The object which was replaced.
465      * throws IndexOutOfBoundsException if index < 0 || index >= size()
466      */

467     Object JavaDoc set(int index, Attribute attribute) {
468         if (index < 0 || index >= size)
469             throw new IndexOutOfBoundsException JavaDoc("Index: " + index +
470                                                 " Size: " + size());
471
472         if (attribute.getParent() != null) {
473             throw new IllegalAddException(
474                           "The attribute already has an existing parent \"" +
475                           attribute.getParent().getQualifiedName() + "\"");
476         }
477
478         String JavaDoc reason = Verifier.checkNamespaceCollision(attribute, parent);
479         if (reason != null) {
480             throw new IllegalAddException(parent, attribute, reason);
481         }
482
483         Attribute old = (Attribute) elementData[index];
484         old.setParent(null);
485
486         elementData[index] = attribute;
487         attribute.setParent(parent);
488         return old;
489     }
490
491     /**
492      * Return index of attribute with same name and Namespace, or
493      * -1 if one doesn't exist
494      */

495     private int indexOfDuplicate(Attribute attribute) {
496         int duplicate = -1;
497         String JavaDoc name = attribute.getName();
498         Namespace namespace = attribute.getNamespace();
499         duplicate = indexOf(name, namespace);
500         return duplicate;
501     }
502
503     /**
504      * Return the number of items in this list
505      *
506      * @return The number of items in this list.
507      */

508     public int size() {
509         return size;
510     }
511
512     /**
513      * Return this list as a <code>String</code>
514      */

515     public String JavaDoc toString() {
516         return super.toString();
517     }
518 }
519
Popular Tags