001/*
002 *  Copyright 2001-2010 Stephen Colebourne
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.joda.primitives.collection.impl;
017
018import java.util.Collection;
019import java.util.Iterator;
020import java.util.NoSuchElementException;
021
022import org.joda.primitives.ShortUtils;
023import org.joda.primitives.collection.ShortCollection;
024import org.joda.primitives.iterator.ShortIterator;
025
026/**
027 * Array based implementation of <code>ShortCollection</code> for
028 * primitive <code>short</code> elements.
029 * <p>
030 * This collection implementation allows multiple copies of the same value to be added.
031 * Internally, it uses an array, and behaves much like a list.
032 * <p>
033 * This class implements {@link java.util.Collection Collection} allowing
034 * seamless integration with other APIs.
035 * <p>
036 * Add, Remove and Clear are supported.
037 *
038 * @author Stephen Colebourne
039 * @author Jason Tiscione
040 * @version CODE GENERATED
041 * @since 1.0
042 */
043public class ArrayShortCollection extends AbstractShortCollection implements Cloneable {
044    // This file is CODE GENERATED. Do not change manually.
045
046    /** The minimum size allowed when growth occurs */
047    private static final int MIN_GROWTH_SIZE = 4;
048    /** The amount the collection grows by when resized (3/2) */
049    private static final int GROWTH_FACTOR_MULTIPLIER = 3;
050    /** The amount the collection grows by when resized (3/2) */
051    private static final int GROWTH_FACTOR_DIVISOR = 2;
052
053    /** The array of elements */
054    private short[] data;
055    /** The current size */
056    private int size;
057
058    /**
059     * Constructor.
060     */
061    public ArrayShortCollection() {
062        super();
063        data = ShortUtils.EMPTY_SHORT_ARRAY;
064    }
065
066    /**
067     * Constructor that defines an initial size for the internal storage array.
068     *
069     * @param initialSize  the initial size of the internal array, negative treated as zero
070     */
071    public ArrayShortCollection(int initialSize) {
072        super();
073        if (initialSize <= 0) {
074            data = ShortUtils.EMPTY_SHORT_ARRAY;
075        } else {
076            data = new short[initialSize];
077        }
078    }
079
080    /**
081     * Constructor that copies the specified values.
082     *
083     * @param values  an array of values to copy, null treated as zero size array
084     */
085    public ArrayShortCollection(short[] values) {
086        super();
087        if (values == null) {
088            data = ShortUtils.EMPTY_SHORT_ARRAY;
089        } else {
090            data = (short[]) values.clone();
091            size = values.length;
092        }
093    }
094
095    /**
096     * Constructs a new collection by copying values from another collection.
097     *
098     * @param coll  a collection of values to copy, null treated as zero size collection
099     */
100    public ArrayShortCollection(Collection<?> coll) {
101        super();
102        if (coll == null) {
103            data = ShortUtils.EMPTY_SHORT_ARRAY;
104        } else if (coll instanceof ShortCollection) {
105            ShortCollection c = (ShortCollection) coll;
106            size = c.size();
107            data = new short[size];
108            c.toShortArray(data, 0);
109        } else {
110            data = toPrimitiveArray(coll);
111            size = coll.size();
112        }
113    }
114
115    /**
116     * Constructs a new collection by copying values from an iterator.
117     *
118     * @param it  an iterator of values to extract, null treated as zero size collection
119     */
120    public ArrayShortCollection(Iterator<Short> it) {
121        super();
122        if (it == null) {
123            data = ShortUtils.EMPTY_SHORT_ARRAY;
124        } else if (it instanceof ShortIterator) {
125            ShortIterator typed = (ShortIterator) it;
126            data = new short[MIN_GROWTH_SIZE];
127            while (typed.hasNext()) {
128                add(typed.nextShort());
129            }
130        } else {
131            data = new short[MIN_GROWTH_SIZE];
132            while (it.hasNext()) {
133                add(it.next());
134            }
135        }
136    }
137
138    // Implementation
139    //-----------------------------------------------------------------------
140    /**
141     * Gets the current size of the collection.
142     *
143     * @return the current size
144     */
145    public int size() {
146        return size;
147    }
148
149    /**
150     * Gets an iterator over this collection capable of accessing the primitive values.
151     *
152     * @return an iterator over this collection
153     */
154    public ShortIterator iterator() {
155        return new PIterator(this);
156    }
157
158    /**
159     * Adds a primitive value to this collection.
160     *
161     * @param value  the value to add to this collection
162     * @return <code>true</code> if this collection was modified by this method call
163     * @throws IllegalArgumentException if value is rejected by this collection
164     */
165    public boolean add(short value) {
166        ensureCapacity(size + 1);
167        data[size++] = value;
168        return true;
169    }
170
171    // Overrides
172    //-----------------------------------------------------------------------
173    /**
174     * Optimizes the implementation.
175     * <p>
176     * This implementation changes the internal array to be the same size as
177     * the size of the collection.
178     */
179    public void optimize() {
180        if (size < data.length) {
181            short[] array = new short[size];
182            System.arraycopy(data, 0, array, 0, size);
183            data = array;
184        }
185    }
186
187    /**
188     * Are the add methods supported.
189     *
190     * @return <code>true</code>
191     */
192    protected boolean isAddModifiable() {
193        return true;
194    }
195
196    /**
197     * Are the remove methods supported.
198     *
199     * @return <code>true</code>
200     */
201    protected boolean isRemoveModifiable() {
202        return true;
203    }
204
205    /**
206     * Checks whether the object can currently be modified.
207     *
208     * @return <code>true</code>
209     */
210    public boolean isModifiable() {
211        return true;
212    }
213
214    /**
215     * Checks whether this collection contains a specified primitive value.
216     * <p>
217     * This implementation uses the internal array directly.
218     *
219     * @param value  the value to search for
220     * @return <code>true</code> if the value is found
221     */
222    public boolean contains(short value) {
223        for (int i = 0; i < size; i++) {
224            if (data[i] == value) {
225                return true;
226            }
227        }
228        return false;
229    }
230
231    /**
232     * Clears the collection of all elements.
233     * The collection will have a zero size after this method completes.
234     * <p>
235     * This implementation resets the size, but does not reduce the internal storage array.
236     */
237    public void clear() {
238        size = 0;
239    }
240
241    /**
242     * Adds an array of primitive values to this collection.
243     *
244     * @param values  the values to add to this collection
245     * @return <code>true</code> if this collection was modified by this method call
246     */
247    public boolean addAll(short[] values) {
248        checkAddModifiable();
249        if (values == null || values.length == 0) {
250            return false;
251        }
252        return doAdd(0, values);
253    }
254
255    /**
256     * Adds a collection of primitive values to this collection.
257     *
258     * @param values  the values to add to this collection, null treated as empty collection
259     * @return <code>true</code> if this collection was modified by this method call
260     */
261    public boolean addAll(ShortCollection values) {
262        checkAddModifiable();
263        if (values == null || values.size() == 0) {
264            return false;
265        }
266        int len = values.size();
267        ensureCapacity(size + len);
268        values.toShortArray(data, size);
269        size += len;
270        return true;
271    }
272
273    /**
274     * Adds a range of primitive values to this collection.
275     * <p>
276     * The range is defined to be inclusive of the start and end.
277     * If the start is greater than the end then the range is equivalent to an empty collection.
278     *
279     * @param startInclusive  the inclusive range start value
280     * @param endInclusive  the inclusive range end value
281     * @return <code>true</code> if this collection was modified by this method call
282     * @throws IllegalArgumentException if a value is rejected by this set
283     * @throws UnsupportedOperationException if not supported by this set
284     */
285    public boolean addAll(short startInclusive, short endInclusive) {
286        int increase = endInclusive - startInclusive + 1;
287        if (increase < 0) {
288            return false;
289        }
290        ensureCapacity(size + increase);
291        short i = startInclusive;
292        while (i < endInclusive) {
293            data[size++] = i++;
294        }
295        data[size++] = i;  // handles endInclusive=MAX_VALUE
296        return true;
297    }
298
299    /**
300     * Clone implementation that calls Object clone().
301     *
302     * @return the clone
303     */
304    public Object clone() {
305        ArrayShortCollection cloned = (ArrayShortCollection) super.clone();
306        cloned.data = (short[]) data.clone();
307        return cloned;
308    }
309
310    /**
311     * Copies data from this collection into the specified array.
312     * This method is pre-validated.
313     *
314     * @param fromIndex  the index to start from
315     * @param dest  the destination array
316     * @param destIndex  the destination start index
317     * @param size  the number of items to copy
318     */
319    protected void arrayCopy(int fromIndex, short[] dest, int destIndex, int size) {
320        System.arraycopy(data, fromIndex, dest, destIndex, size);
321    }
322
323    // Internal implementation
324    //-----------------------------------------------------------------------
325    /**
326     * Internal implementation to add to this collection at the specified index.
327     * This method adjusts the capacity and size.
328     * 
329     * @param index  the index to add at, valid
330     * @param values  the array to add, not null
331     * @return true if the array was updated
332     */
333    protected boolean doAdd(int index, short[] values) {
334        int len = values.length;
335        ensureCapacity(size + len);
336        System.arraycopy(values, 0, data, size, len);
337        size += len;
338        return (len > 0);
339    }
340
341    /**
342     * Internal implementation to remove the element at the specified index.
343     * 
344     * @param index  the index, valid
345     */
346    protected void doRemoveIndex(int index) {
347        System.arraycopy(data, index + 1, data, index, size - 1 - index);
348        size--;
349    }
350
351    /**
352     * Internal implementation to ensure that the internal storage array has
353     * at least the specified size.
354     * 
355     * @param reqCapacity  the amount to expand to
356     */
357    protected void ensureCapacity(int reqCapacity) {
358        int curCapacity = data.length;
359        if (reqCapacity <= curCapacity) {
360            return;
361        }
362        int newCapacity = curCapacity * GROWTH_FACTOR_MULTIPLIER / GROWTH_FACTOR_DIVISOR;
363        if ((newCapacity - curCapacity) < MIN_GROWTH_SIZE) {
364            newCapacity = curCapacity + MIN_GROWTH_SIZE;
365        }
366        if (newCapacity < reqCapacity) {
367            newCapacity = reqCapacity;
368        }
369        short[] newArray = new short[newCapacity];
370        System.arraycopy(data, 0, newArray, 0, curCapacity);
371        data = newArray;
372    }
373
374    // Iterator
375    //-----------------------------------------------------------------------
376    /**
377     * Iterator.
378     */
379    protected static class PIterator implements ShortIterator {
380
381        private final ArrayShortCollection collection;
382        private int cursor = 0;
383        private boolean canRemove = false;
384
385        protected PIterator(ArrayShortCollection coll) {
386            super();
387            this.collection = coll;
388        }
389
390        public boolean hasNext() {
391            return (cursor < collection.size);
392        }
393
394        public short nextShort() {
395            if (hasNext() == false) {
396                throw new NoSuchElementException("No more elements available");
397            }
398            canRemove = true;
399            return collection.data[cursor++];
400        }
401
402        public Short next() {
403            return collection.toObject(nextShort());
404        }
405
406        public void remove() {
407            if (canRemove == false) {
408                throw new IllegalStateException("Element cannot be removed");
409            }
410            collection.doRemoveIndex(--cursor);
411            canRemove = false;
412        }
413
414        public boolean isModifiable() {
415            return collection.isModifiable();
416        }
417
418        public boolean isResettable() {
419            return true;
420        }
421
422        public void reset() {
423            cursor = 0;
424        }
425    }
426
427}