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