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.lang.reflect.Array;
019import java.util.Collection;
020import java.util.Iterator;
021
022import org.joda.primitives.DoubleUtils;
023import org.joda.primitives.collection.DoubleCollection;
024import org.joda.primitives.iterator.DoubleIterator;
025
026/**
027 * Abstract base class for collections of primitive <code>double</code> elements.
028 * <p>
029 * This class implements {@link java.util.Collection Collection} allowing
030 * seamless integration with other APIs.
031 * <p>
032 * The <code>iterator</code> and <code>size</code> must be implemented by subclases.
033 * To make the subclass modifiable, the <code>add(double)</code> and
034 * iterator <code>remove()</code> methods must also be implemented.
035 * Subclasses may override other methods to increase efficiency.
036 *
037 * @author Stephen Colebourne
038 * @author Jason Tiscione
039 * @version CODE GENERATED
040 * @since 1.0
041 */
042public abstract class AbstractDoubleCollection
043        extends AbstractPrimitiveCollectable<Double>
044        implements DoubleCollection {
045    // This file is CODE GENERATED. Do not change manually.
046
047    /**
048     * Constructor.
049     */
050    protected AbstractDoubleCollection() {
051        super();
052    }
053    
054    // Mandatory operations
055    //-----------------------------------------------------------------------
056    /**
057     * Checks whether this collection contains a specified primitive value.
058     * <p>
059     * This implementation uses <code>doubleIterator()</code>.
060     *
061     * @param value  the value to search for
062     * @return <code>true</code> if the value is found
063     */
064    public boolean contains(double value) {
065        for (DoubleIterator it = iterator(); it.hasNext();) {
066            if (it.nextDouble() == value) {
067                return true;
068            }
069        }
070        return false;
071    }
072
073    /**
074     * Checks if this collection contains all of the values in the specified array.
075     * If the specified array is empty, <code>true</code> is returned.
076     * <p>
077     * This implementation uses <code>contains(double)</code>.
078     *
079     * @param values  the values to search for, null treated as empty array
080     * @return <code>true</code> if all of the values are found
081     */
082    public boolean containsAll(double[] values) {
083        if (values != null) {
084            for (int i = 0; i < values.length; i++) {
085                if (contains(values[i]) == false) {
086                    return false;
087                }
088            }
089        }
090        return true;
091    }
092
093    /**
094     * Checks if this collection contains all of the values in the specified collection.
095     * If the specified collection is empty, <code>true</code> is returned.
096     * <p>
097     * This implementation uses <code>contains(double)</code>.
098     *
099     * @param values  the values to search for, null treated as empty collection
100     * @return <code>true</code> if all of the values are found
101     */
102    public boolean containsAll(DoubleCollection values) {
103        if (values != null) {
104            for (DoubleIterator it = values.iterator(); it.hasNext(); ) {
105                if (contains(it.nextDouble()) == false) {
106                    return false;
107                }
108            }
109        }
110        return true;
111    }
112
113    /**
114     * Checks if this collection contains any of the values in the specified array.
115     * If the specified array is empty, <code>false</code> is returned.
116     * <p>
117     * This implementation uses <code>contains(double)</code>.
118     *
119     * @param values  the values to search for, null treated as empty array
120     * @return <code>true</code> if at least one of the values is found
121     */
122    public boolean containsAny(double[] values) {
123        if (values != null) {
124            for (int i = 0; i < values.length; i++) {
125                if (contains(values[i])) {
126                    return true;
127                }
128            }
129        }
130        return false;
131    }
132
133    /**
134     * Checks if this collection contains any of the values in the specified collection.
135     * If the specified collection is empty, <code>false</code> is returned.
136     * <p>
137     * This implementation uses <code>contains(double)</code>.
138     *
139     * @param values  the values to search for, null treated as empty collection
140     * @return <code>true</code> if at least one of the values is found
141     */
142    public boolean containsAny(DoubleCollection values) {
143        if (values != null) {
144            for (DoubleIterator it = values.iterator(); it.hasNext(); ) {
145                if (contains(it.nextDouble())) {
146                    return true;
147                }
148            }
149        }
150        return false;
151    }
152
153    /**
154     * Gets the elements of this collection as an array.
155     * <p>
156     * This implementation uses <code>arrayCopy</code>.
157     *
158     * @return a new array containing a copy of the elements of this collection
159     */
160    public double[] toDoubleArray() {
161        if (size() == 0) {
162            return DoubleUtils.EMPTY_DOUBLE_ARRAY;
163        }
164        double[] result = new double[size()];
165        arrayCopy(0, result, 0, size());
166        return result;
167    }
168
169    /**
170     * Copies the elements of this collection into an array at a specified position.
171     * Previous values in the array are overwritten.
172     * <p>
173     * If the array specified is null a new array is created.
174     * If the array specified is large enough, it will be modified.
175     * If the array is not large enough, a new array will be created containing the
176     * values from the specified array before the startIndex plus those from this collection.
177     * <p>
178     * This implementation uses <code>arrayCopy</code>.
179     *
180     * @param array  the array to add the elements to, null treated as empty array
181     * @param startIndex  the position in the array to start setting elements
182     * @return the array with the populated collection
183     * @throws IndexOutOfBoundsException if the index is negative
184     */
185    public double[] toDoubleArray(double[] array, int startIndex) {
186        if (startIndex < 0) {
187            throw new IndexOutOfBoundsException("Start index must not be negative: " + startIndex);
188        }
189        double[] result = null;
190        if (array == null) {
191            // create new
192            result = new double[startIndex + size()];
193            
194        } else if (array.length - startIndex - size() >= 0) {
195            // room to fit data
196            result = array;
197            
198        } else {
199            // expand array
200            result = new double[startIndex + size()];
201            System.arraycopy(array, 0, result, 0, startIndex);
202        }
203        arrayCopy(0, result, startIndex, size());
204        return result;
205    }
206
207    // Optional operations
208    //-----------------------------------------------------------------------
209    /**
210     * Clears the collection/map of all elements (optional operation).
211     * <p>
212     * The collection/map will have a zero size after this method completes.
213     * This method is optional, throwing an UnsupportedOperationException if the
214     * collection/map cannot be cleared.
215     * <p>
216     * This implementation uses <code>iterator()</code>.
217     *
218     * @throws UnsupportedOperationException if method not supported by this collection
219     */
220    public void clear() {
221        checkRemoveModifiable();
222        for (DoubleIterator it = iterator(); it.hasNext();) {
223            it.nextDouble();
224            it.remove();
225        }
226    }
227
228    /**
229     * Adds a primitive value to this collection (optional operation).
230     * <p>
231     * This implementation throws UnsupportedOperationException.
232     *
233     * @param value  the value to add to this collection
234     * @return <code>true</code> if this collection was modified by this method call
235     * @throws IllegalArgumentException if value is rejected by this collection
236     * @throws UnsupportedOperationException if not supported by this collection
237     */
238    public boolean add(double value) {
239        throw new UnsupportedOperationException("Collection does not support add");
240    }
241
242    /**
243     * Adds an array of primitive values to this collection (optional operation).
244     * <p>
245     * This implementation uses <code>add(double)</code>.
246     *
247     * @param values  the values to add to this collection, null treated as empty array
248     * @return <code>true</code> if this collection was modified by this method call
249     * @throws IllegalArgumentException if a value is rejected by this collection
250     * @throws UnsupportedOperationException if not supported by this collection
251     */
252    public boolean addAll(double[] values) {
253        checkAddModifiable();
254        boolean changed = false;
255        if (values != null) {
256            for (int i = 0; i < values.length; i++) {
257                changed |= add(values[i]);
258            }
259        }
260        return changed;
261    }
262
263    /**
264     * Adds a collection of primitive values to this collection (optional operation).
265     * <p>
266     * This implementation uses <code>add(double)</code>.
267     *
268     * @param values  the values to add to this collection, null treated as empty collection
269     * @return <code>true</code> if this collection was modified by this method call
270     * @throws IllegalArgumentException if a value is rejected by this collection
271     * @throws UnsupportedOperationException if not supported by this collection
272     */
273    public boolean addAll(DoubleCollection values) {
274        checkAddModifiable();
275        boolean changed = false;
276        if (values != null) {
277            for (DoubleIterator it = values.iterator(); it.hasNext(); ) {
278                changed |= add(it.nextDouble());
279            }
280        }
281        return changed;
282    }
283
284    /**
285     * Removes the first occurrence of the specified primitive value from this collection
286     * <p>
287     * This implementation uses <code>iterator().remove()</code>.
288     *
289     * @param value  the value to remove
290     * @return <code>true</code> if this collection was modified by this method call
291     * @throws UnsupportedOperationException if not supported by this collection
292     */
293    public boolean removeFirst(double value) {
294        checkRemoveModifiable();
295        for (DoubleIterator it = iterator(); it.hasNext(); ) {
296            if (it.nextDouble() == value) {
297                it.remove();
298                return true;
299            }
300        }
301        return false;
302    }
303
304    /**
305     * Removes all occurrences of the specified primitive value from this collection.
306     * <p>
307     * This implementation uses <code>iterator().remove()</code>.
308     *
309     * @param value  the value to remove
310     * @return <code>true</code> if this collection was modified by this method call
311     * @throws UnsupportedOperationException if not supported by this collection
312     */
313    public boolean removeAll(double value) {
314        checkRemoveModifiable();
315        boolean changed = false;
316        for (DoubleIterator it = iterator(); it.hasNext(); ) {
317            if (it.nextDouble() == value) {
318                it.remove();
319                changed = true;
320            }
321        }
322        return changed;
323    }
324
325    /**
326     * Removes all occurrences from this collection of each primitive in the specified array.
327     * <p>
328     * This implementation uses <code>iterator().remove()</code>.
329     *
330     * @param values  the values to remove from this collection, null treated as empty array
331     * @return <code>true</code> if this list was modified by this method call
332     * @throws UnsupportedOperationException if not supported by this collection
333     */
334    public boolean removeAll(double[] values) {
335        checkRemoveModifiable();
336        boolean changed = false;
337        if (values != null) {
338            for (DoubleIterator it = iterator(); it.hasNext(); ) {
339                double value = it.nextDouble();
340                for (int i = 0; i < values.length; i++) {
341                    if (values[i] == value) {
342                        it.remove();
343                        changed = true;
344                    }
345                }
346            }
347        }
348        return changed;
349    }
350
351    /**
352     * Removes all occurrences from this collection of each primitive in the specified collection.
353     * <p>
354     * This implementation uses <code>iterator().remove()</code>.
355     *
356     * @param values  the values to remove from this collection, null treated as empty collection
357     * @return <code>true</code> if this list was modified by this method call
358     * @throws UnsupportedOperationException if not supported by this collection
359     */
360    public boolean removeAll(DoubleCollection values) {
361        checkRemoveModifiable();
362        boolean changed = false;
363        if (values != null) {
364            for (DoubleIterator it = iterator(); it.hasNext(); ) {
365                if (values.contains(it.nextDouble())) {
366                    it.remove();
367                    changed = true;
368                }
369            }
370        }
371        return changed;
372    }
373
374    /**
375     * Retains each element of this collection that is present in the specified array
376     * removing all other values.
377     * <p>
378     * This implementation uses <code>iterator().remove()</code>.
379     *
380     * @param values  the values to remove from this collection, null treated as empty array
381     * @return <code>true</code> if this list was modified by this method call
382     * @throws UnsupportedOperationException if not supported by this collection
383     */
384    public boolean retainAll(double[] values) {
385        checkRemoveModifiable();
386        boolean changed = false;
387        if (values == null || values.length == 0) {
388            changed = !isEmpty();
389            clear();
390        } else {
391            for (DoubleIterator it = iterator(); it.hasNext(); ) {
392                double next = it.nextDouble();
393                boolean match = false;
394                for (int i = 0; i < values.length; i++) {
395                    if (values[i] == next) {
396                        match = true;
397                        break;
398                    }
399                }
400                if (match == false) {
401                    it.remove();
402                    changed = true;
403                }
404            }
405        }
406        return changed;
407    }
408
409    /**
410     * Retains each element of this collection that is present in the specified collection
411     * removing all other values.
412     * <p>
413     * This implementation uses <code>iterator().remove()</code>.
414     *
415     * @param values  the values to retain in this collection, null treated as empty collection
416     * @return <code>true</code> if this collection was modified by this method call
417     * @throws UnsupportedOperationException if not supported by this collection
418     */
419    public boolean retainAll(DoubleCollection values) {
420        checkRemoveModifiable();
421        boolean changed = false;
422        if (values == null || values.isEmpty()) {
423            changed = !isEmpty();
424            clear();
425        } else {
426            for (DoubleIterator it = iterator(); it.hasNext(); ) {
427                if (values.contains(it.nextDouble()) == false) {
428                    it.remove();
429                    changed = true;
430                }
431            }
432        }
433        return changed;
434    }
435
436    // Collection integration
437    //-----------------------------------------------------------------------
438    /**
439     * Checks whether this collection contains a specified <code>Double</code> value.
440     * <p>
441     * This implementation uses <code>contains(double)</code>.
442     *
443     * @param value  the value to search for
444     * @return <code>true</code> if the value is found
445     */
446    public boolean contains(Object value) {
447        return contains(toPrimitive(value));
448    }
449
450    /**
451     * Checks if the collection contains all of the primitive values.
452     * <p>
453     * This implementation uses <code>containsAll(double[])</code>.
454     *
455     * @param coll  the collection of values to search for
456     * @return <code>true</code> if all the values are found
457     */
458    public boolean containsAll(Collection<?> coll) {
459        if (coll == this || coll.size() == 0) {
460            return true;
461        }
462        if (size() == 0) {
463            return false;
464        }
465        return containsAll(toPrimitiveArray(coll));
466    }
467
468    /**
469     * Checks if the collection contains any of the primitive values in the array.
470     * If the specified collection is empty, <code>false</code> is returned.
471     * <p>
472     * This implementation uses <code>containsAny(double[])</code>.
473     *
474     * @param coll  the collection of values to search for
475     * @return <code>true</code> if at least one of the values is found
476     */
477    public boolean containsAny(Collection<?> coll) {
478        if (size() == 0 || coll.size() == 0) {
479            return false;
480        }
481        if (coll == this) {
482            return true;
483        }
484        return containsAny(toPrimitiveArray(coll));
485    }
486
487    /**
488     * Gets the collection as an array of <code>Double</code>.
489     * 
490     * @return an array of <code>Double</code>
491     */
492    public Object[] toArray() {
493        Object[] result = new Double[size()];
494        DoubleIterator it = iterator();
495        for (int i = 0; it.hasNext(); i++) {
496            result[i] = it.next();
497        }
498        return result;
499    }
500
501    /**
502     * Gets the collection as an array, using the array provided.
503     * 
504     * @param array  the array to populate
505     * @return an array of <code>Double</code>
506     */
507    @SuppressWarnings("unchecked")
508    public <T> T[] toArray(T[] array) {
509        int size = size();
510        if (array.length < size) {
511          array = (T[]) Array.newInstance(array.getClass().getComponentType(), size);
512        }
513
514        Iterator<Double> it = iterator();
515        for (int i = 0; i < size; i++) {
516            array[i] = (T)it.next();
517        }
518
519        if (array.length > size) {
520            array[size] = null;
521        }
522        
523        return array;
524    }
525
526    /**
527     * Adds the <code>Double</code> value to this collection (optional operation).
528     * <p>
529     * This method is optional, throwing an UnsupportedOperationException if the
530     * collection cannot be added to.
531     * <p>
532     * This implementation uses <code>add(double)</code>.
533     *
534     * @param value  the value to add to this collection
535     * @return <code>true</code> if this collection was modified by this method call
536     * @throws IllegalArgumentException if value is rejected by this collection
537     * @throws UnsupportedOperationException if not supported by this collection
538     */
539    public boolean add(Double value) {
540        checkAddModifiable();
541        return add(toPrimitive(value));
542    }
543
544    /**
545     * Adds a collection of <code>Double</code> values to this collection (optional operation).
546     * <p>
547     * This method is optional, throwing an UnsupportedOperationException if the
548     * collection cannot be added to.
549     * <p>
550     * This implementation uses <code>addAll(double[])</code>.
551     *
552     * @param coll  the values to add to this collection
553     * @return <code>true</code> if this list was modified by this method call
554     * @throws IndexOutOfBoundsException if the index is invalid
555     * @throws ClassCastException if any object is not <code>Double</code>
556     * @throws IllegalArgumentException if value is rejected by this collection
557     * @throws UnsupportedOperationException if not supported by this collection
558     */
559    public boolean addAll(Collection<? extends Double> coll) {
560        checkAddModifiable();
561        return addAll(toPrimitiveArray(coll));
562    }
563
564    /**
565     * Removes the first occurrance of the specified <code>Double</code> value from
566     * this collection (optional operation).
567     * <p>
568     * This method is optional, throwing an UnsupportedOperationException if the
569     * collection cannot be removed from.
570     * <p>
571     * This implementation uses <code>removeFirst(double)</code>.
572     *
573     * @param value  the value to remove
574     * @return <code>true</code> if this collection was modified by this method call
575     * @throws UnsupportedOperationException if not supported by this collection
576     */
577    public boolean remove(Object value) {
578        checkRemoveModifiable();
579        return removeFirst(toPrimitive(value));
580    }
581
582    /**
583     * Removes each of a collection of <code>Double</code> values from this collection (optional operation).
584     * <p>
585     * This method is optional, throwing an UnsupportedOperationException if the
586     * collection cannot be added to.
587     * <p>
588     * This implementation uses <code>removeAll(double[])</code>.
589     *
590     * @param coll  the values to remove from this collection
591     * @return <code>true</code> if this list was modified by this method call
592     * @throws UnsupportedOperationException if not supported by this collection
593     */
594    public boolean removeAll(Collection<?> coll) {
595        checkRemoveModifiable();
596        if (coll == this) {
597            int size = size();
598            clear();
599            return (size() != size);
600        }
601        return removeAll(toPrimitiveArray(coll));
602    }
603
604    /**
605     * Retains each of a collection of <code>Double</code> values, removing other
606     * values (optional operation).
607     * <p>
608     * This method is optional, throwing an UnsupportedOperationException if the
609     * collection cannot be added to.
610     * <p>
611     * This implementation uses <code>retainAll(double[])</code>.
612     *
613     * @param coll  the values to retain in this collection
614     * @return <code>true</code> if this list was modified by this method call
615     * @throws UnsupportedOperationException if not supported by this collection
616     */
617    public boolean retainAll(Collection<?> coll) {
618        checkRemoveModifiable();
619        if (coll == this) {
620            return false;
621        }
622        return retainAll(toPrimitiveArray(coll));
623    }
624
625    // Basics
626    //-----------------------------------------------------------------------
627    /**
628     * Gets a string representing this collection.
629     * <p>
630     * The format used is as per <code>Collection</code>.
631     * 
632     * @return collection as a String
633     */
634    public String toString() {
635        StringBuffer buf = new StringBuffer();
636        buf.append("[");
637
638        DoubleIterator it = iterator();
639        boolean hasNext = it.hasNext();
640        while (hasNext) {
641            buf.append(it.nextDouble());
642            hasNext = it.hasNext();
643            if (hasNext) {
644                buf.append(", ");
645            }
646        }
647
648        buf.append("]");
649        return buf.toString();
650    }
651    
652    // Internals
653    //-----------------------------------------------------------------------
654    /**
655     * Copies data from this collection into the specified array.
656     * This method is pre-validated.
657     * 
658     * @param fromIndex  the index to start from
659     * @param dest  the destination array
660     * @param destIndex  the destination start index
661     * @param size  the number of items to copy
662     */
663    protected void arrayCopy(int fromIndex, double[] dest, int destIndex, int size) {
664        DoubleIterator it = iterator();
665        for (int i = 0; it.hasNext() && i < size; i++) {
666            dest[destIndex + i] = it.nextDouble();
667        }
668    }
669
670    /**
671     * Are the add methods supported.
672     * <p>
673     * This implementation returns false.
674     *
675     * @return true if supported
676     */
677    protected boolean isAddModifiable() {
678        return false;
679    }
680
681    /**
682     * Are the remove methods supported.
683     * <p>
684     * This implementation returns false.
685     *
686     * @return true if supported
687     */
688    protected boolean isRemoveModifiable() {
689        return false;
690    }
691
692    /**
693     * Is the collection modifiable in any way.
694     *
695     * @return true if supported
696     */
697    public boolean isModifiable() {
698        return isAddModifiable() || isRemoveModifiable();
699    }
700
701    /**
702     * Check whether add is suported and throw an exception.
703     */
704    protected void checkAddModifiable() {
705        if (isAddModifiable() == false) {
706            throw new UnsupportedOperationException("Collection does not support add");
707        }
708    }
709
710    /**
711     * Check whether remove is suported and throw an exception.
712     */
713    protected void checkRemoveModifiable() {
714        if (isRemoveModifiable() == false) {
715            throw new UnsupportedOperationException("Collection does not support remove");
716        }
717    }
718
719    /**
720     * Wraps an <code>double</code> with an Object wrapper.
721     * 
722     * @param value  the primitive value
723     * @return the Object wrapper
724     */
725    protected Double toObject(double value) {
726        return DoubleUtils.toObject(value);
727    }
728
729    /**
730     * Checks if the object can be converted to a primitive successfully.
731     * <p>
732     * This implementation only allows non-null Double objects.
733     * 
734     * @param value  the Object wrapper
735     * @return true if a primitive value can be successfully extracted
736     */
737    protected boolean isToPrimitivePossible(Object value) {
738        return (value instanceof Double);
739    }
740
741    /**
742     * Unwraps the <code>Double</code> to retrieve the primitive <code>double</code>.
743     * <p>
744     * This implementation only allows non-null Double objects.
745     * 
746     * @param value  the Object to convert to a primitive
747     * @return the primitive value
748     * @throws NullPointerException if the value is null and this is unacceptable
749     * @throws ClassCastException if the object is of an unsuitable type
750     */
751    protected double toPrimitive(Object value) {
752        return DoubleUtils.toPrimitive(value);
753    }
754
755    /**
756     * Unwraps a <code>Collection</code> to retrieve the primitive <code>double</code>.
757     * <p>
758     * This implementation only allows non-null Double objects.
759     * 
760     * @param coll  the Collection to convert to primitives
761     * @return the primitive value
762     * @throws NullPointerException if the value is null and this is unacceptable
763     * @throws ClassCastException if any object is of an unsuitable type
764     */
765    protected double[] toPrimitiveArray(Collection<?> coll) {
766        return DoubleUtils.toPrimitiveArray(coll);
767    }
768
769}