View Javadoc
1   /*
2    * Redistribution and use of this software and associated documentation ("Software"), with or
3    * without modification, are permitted provided that the following conditions are met:
4    *
5    * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
6    * must also contain a copy of this document.
7    *
8    * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
9    * conditions and the following disclaimer in the documentation and/or other materials provided with
10   * the distribution.
11   *
12   * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
13   * without prior written permission of Intalio, Inc. For written permission, please contact
14   * info@exolab.org.
15   *
16   * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
17   * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
18   * Intalio, Inc.
19   *
20   * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
21   *
22   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
23   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
25   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29   * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30   *
31   * Copyright 2002 (C) Intalio, Inc. All Rights Reserved.
32   *
33   * $Id$
34   */
35  package org.exolab.castor.xml.util;
36  
37  import org.exolab.castor.xml.XMLFieldDescriptor;
38  
39  /**
40   * A class which represents a collection of XMLFieldDescriptor instances.
41   *
42   * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
43   * @version $Revision$ $Date: 2005-12-13 14:58:48 -0700 (Tue, 13 Dec 2005) $
44   * @see java.util.List
45   * @see java.util.Collection
46   */
47  public class XMLFieldDescriptors {
48  
49    private static final int DEFAULT_SIZE = 11;
50  
51    private XMLFieldDescriptor[] _elements;
52  
53    /**
54     * The next available location in the elements array.
55     */
56    private int _elementCount = 0;
57  
58    /**
59     * Creates a new XMLFieldDescriptors with the default Size.
60     */
61    public XMLFieldDescriptors() {
62      _elements = new XMLFieldDescriptor[DEFAULT_SIZE];
63    } // -- XMLFieldDescriptors
64  
65    /**
66     * Creates a new XMLFieldDescriptors with the given size.
67     *
68     * @param size the initial size of the internal collection.
69     */
70    public XMLFieldDescriptors(int size) {
71      _elements = new XMLFieldDescriptor[size];
72    } // -- XMLFieldDescriptors
73  
74    /**
75     * Adds the specified XMLFieldDescriptor to the collection. If the specified XMLFieldDescriptor is
76     * already contained in the collection, it will not be re-added, false will be returned.
77     *
78     * @param descriptor the XMLFieldDescriptor to add
79     * @return true if the descriptor is added, false otherwise.
80     */
81    public boolean add(XMLFieldDescriptor descriptor) {
82  
83      for (int i = 0; i < _elementCount; i++) {
84        if (_elements[i] == descriptor)
85          return false;
86      }
87      if (_elementCount == _elements.length)
88        increaseSize();
89      _elements[_elementCount++] = descriptor;
90      return true;
91    } // -- add
92  
93    /**
94     * Removes all descriptors from this collection.
95     */
96    public void clear() {
97      for (int i = 0; i < _elementCount; i++) {
98        _elements[i] = null;
99      }
100     _elementCount = 0;
101   } // -- clear
102 
103   public Object clone() {
104     Object obj = null;
105     try {
106       obj = super.clone();
107     } catch (CloneNotSupportedException e) {
108       // this should never happen
109     }
110     return obj;
111   } // -- clone
112 
113   /**
114    * Returns true if the specified descriptor is contained in this collection. If the descriptor is
115    * null, then if this collection contains a null value, true will be returned.
116    *
117    * @param descriptor the XMLFieldDescriptor to search the list for
118    * @return true if specified descriptor is contained in the list
119    **/
120   public boolean contains(XMLFieldDescriptor descriptor) {
121     return (indexOf(descriptor) >= 0);
122   } // -- contains
123 
124   /**
125    * Compares the specified object with this list for equality. Returns true if and only if the
126    * specified Object is a list and all of its associated elements are equal to the elements of this
127    * list
128    *
129    * @return true if the given object is considered equal to this list.
130    */
131   public boolean equals(Object obj) {
132     if (obj == null)
133       return false;
134     if (obj == this)
135       return true;
136     if (!(obj instanceof XMLFieldDescriptors))
137       return false;
138     XMLFieldDescriptors descs = (XMLFieldDescriptors) obj;
139     if (descs._elementCount != _elementCount)
140       return false;
141     for (int i = 0; i < _elementCount; i++) {
142       Object e1 = get(i);
143       Object e2 = descs._elements[i];
144       if (!((e1 == null) ? (e2 == null) : e1.equals(e2)))
145         return false;
146     }
147     return true;
148   } // -- equals
149 
150   /**
151    * Returns the XMLFieldDescriptor at the specified position in this list.
152    *
153    * @param index the position of the descriptor to return
154    * @exception IndexOutOfBoundsException
155    */
156   public XMLFieldDescriptor get(int index) throws IndexOutOfBoundsException {
157     if ((index < 0) || index >= _elementCount) {
158       throw new IndexOutOfBoundsException();
159     }
160     return _elements[index];
161   } // -- get
162 
163   /**
164    * As defined by the JDK 1.2 API spec:<BR>
165    * Returns the hash code value for this list. The hash code of a list is defined to be the result
166    * of the following calculation: <BR>
167    * <code>
168    * hashCode = 1;
169    * Iterator i = list.iterator();
170    * while (i.hasNext()) {
171    *    Object obj = i.next();
172    *    hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
173    * }
174    * </code>
175    * 
176    * @return the hash code value for this list
177    */
178   public int hashCode() {
179     int hashCode = 1;
180     for (int i = 0; i < _elementCount; i++) {
181       Object obj = _elements[i];
182       hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
183     }
184     return hashCode;
185   } // -- hashCode
186 
187   /**
188    * Returns the index of the first occurrence of the specified XMLFieldDescriptor, or -1 if the
189    * descriptor is not contained in the collection.
190    *
191    * @param descriptor the XMLFieldDescriptor to get the index of
192    */
193   public int indexOf(XMLFieldDescriptor descriptor) {
194     if (descriptor == null) {
195       for (int i = 0; i < _elementCount; i++) {
196         if (_elements[i] == null)
197           return i;
198       }
199     } else {
200       for (int i = 0; i < _elementCount; i++) {
201         if (descriptor.equals(_elements[i]))
202           return i;
203       }
204     }
205     return -1;
206   } // -- indexOf
207 
208   /**
209    * Returns true if there are no descriptors in the collection.
210    *
211    * @return true if the collection is empty.
212    */
213   public boolean isEmpty() {
214     return (_elementCount == 0);
215   } // -- isEmpty
216 
217   /**
218    * Removes the descriptor at the specified index from the list.
219    *
220    * @param index the position in the list to remove the descriptor from.
221    * @return the descriptor that was removed from the list.
222    */
223   public XMLFieldDescriptor remove(int index) {
224 
225     if ((index < 0) || (index > _elementCount))
226       return null;
227     XMLFieldDescriptor desc = _elements[index];
228     shiftDown(index + 1);
229     --_elementCount;
230     return desc;
231   } // -- remove
232 
233   /**
234    * Removes the given XMLFieldDescriptor from the list.
235    *
236    * @param descriptor the XMLFieldDescriptor to remove from the list.
237    * @return true if the descriptor was removed from the list.
238    */
239   public boolean remove(XMLFieldDescriptor descriptor) {
240     int index = indexOf(descriptor);
241     if (index > -1) {
242       remove(index);
243       return true;
244     }
245     return false;
246   } // -- remove
247 
248   /**
249    * Reduces the capacity of the internal buffer to the current size freeing up unused memory.
250    */
251   public void trimToSize() {
252     if (_elements.length == _elementCount)
253       return;
254     XMLFieldDescriptor[] pointer = _elements;
255     _elements = new XMLFieldDescriptor[_elementCount];
256     System.arraycopy(pointer, 0, _elements, 0, _elementCount);
257     pointer = null;
258   } // -- trimToSize
259 
260   /**
261    * Returns the number of descriptors in the list.
262    *
263    * @return the number of descriptors in the list.
264    */
265   public int size() {
266     return _elementCount;
267   } // -- size
268 
269   /**
270    * Returns an array containing all of the descriptors in this list in proper sequence.
271    *
272    * @return the array of descriptors of this List
273    */
274   public XMLFieldDescriptor[] toArray() {
275     XMLFieldDescriptor[] objArray = new XMLFieldDescriptor[_elementCount];
276     System.arraycopy(_elements, 0, objArray, 0, _elementCount);
277     return objArray;
278   } // -- toArray
279 
280   /**
281    * Returns an array containing all of the descriptors in this list in proper sequence.
282    *
283    * @return the array of descriptors of this list.
284    */
285   public XMLFieldDescriptor[] toArray(XMLFieldDescriptor[] dst) {
286     return toArray(dst, 0);
287   } // -- toArray
288 
289   /**
290    * Returns an array containing all of the elements in this list in proper sequence.
291    *
292    * @return the array of descriptors of this list.
293    */
294   public XMLFieldDescriptor[] toArray(XMLFieldDescriptor[] dst, int offset) {
295 
296     XMLFieldDescriptor[] objArray = null;
297 
298     if (dst.length >= _elementCount)
299       objArray = dst;
300     else {
301       objArray = new XMLFieldDescriptor[_elementCount];
302     }
303     System.arraycopy(_elements, 0, objArray, offset, _elementCount);
304     return objArray;
305   } // -- toArray
306 
307 
308   // -------------------/
309   // - Private Methods -/
310   // -------------------/
311 
312   /**
313    * Basically the same as a vector, increase the list by a factor of its initial size
314    */
315   private void increaseSize() {
316     XMLFieldDescriptor[] pointer = _elements;
317     int length = (pointer.length > 0) ? pointer.length : 1;
318     _elements = new XMLFieldDescriptor[(length * 3) / 2 + 1];
319     System.arraycopy(pointer, 0, _elements, 0, pointer.length);
320     pointer = null;
321   } // -- increaseSize
322 
323   /**
324    * Shifts all elements at the specified index to down by 1
325    */
326   private void shiftDown(int index) {
327     if ((index <= 0) || (index >= _elementCount))
328       return;
329     System.arraycopy(_elements, index, _elements, index - 1, _elementCount - index);
330     // clean up for gc
331     _elements[_elementCount - 1] = null;
332   } // -- shiftDown
333 
334 } // -- XMLFieldDescriptors