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     */
016    package org.joda.primitives.collection.impl;
017    
018    import java.lang.reflect.Array;
019    import java.util.Collection;
020    import java.util.Iterator;
021    
022    import org.joda.primitives.BooleanUtils;
023    import org.joda.primitives.collection.BooleanCollection;
024    import org.joda.primitives.iterator.BooleanIterator;
025    
026    /**
027     * Abstract base class for collections of primitive <code>boolean</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(boolean)</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     */
042    public abstract class AbstractBooleanCollection
043            extends AbstractPrimitiveCollectable<Boolean>
044            implements BooleanCollection {
045        // This file is CODE GENERATED. Do not change manually.
046    
047        /**
048         * Constructor.
049         */
050        protected AbstractBooleanCollection() {
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>booleanIterator()</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(boolean value) {
065            for (BooleanIterator it = iterator(); it.hasNext();) {
066                if (it.nextBoolean() == 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(boolean)</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(boolean[] 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(boolean)</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(BooleanCollection values) {
103            if (values != null) {
104                for (BooleanIterator it = values.iterator(); it.hasNext(); ) {
105                    if (contains(it.nextBoolean()) == 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(boolean)</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(boolean[] 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(boolean)</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(BooleanCollection values) {
143            if (values != null) {
144                for (BooleanIterator it = values.iterator(); it.hasNext(); ) {
145                    if (contains(it.nextBoolean())) {
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 boolean[] toBooleanArray() {
161            if (size() == 0) {
162                return BooleanUtils.EMPTY_BOOLEAN_ARRAY;
163            }
164            boolean[] result = new boolean[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 boolean[] toBooleanArray(boolean[] array, int startIndex) {
186            if (startIndex < 0) {
187                throw new IndexOutOfBoundsException("Start index must not be negative: " + startIndex);
188            }
189            boolean[] result = null;
190            if (array == null) {
191                // create new
192                result = new boolean[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 boolean[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 (BooleanIterator it = iterator(); it.hasNext();) {
223                it.nextBoolean();
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(boolean 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(boolean)</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(boolean[] 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(boolean)</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(BooleanCollection values) {
274            checkAddModifiable();
275            boolean changed = false;
276            if (values != null) {
277                for (BooleanIterator it = values.iterator(); it.hasNext(); ) {
278                    changed |= add(it.nextBoolean());
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(boolean value) {
294            checkRemoveModifiable();
295            for (BooleanIterator it = iterator(); it.hasNext(); ) {
296                if (it.nextBoolean() == 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(boolean value) {
314            checkRemoveModifiable();
315            boolean changed = false;
316            for (BooleanIterator it = iterator(); it.hasNext(); ) {
317                if (it.nextBoolean() == 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(boolean[] values) {
335            checkRemoveModifiable();
336            boolean changed = false;
337            if (values != null) {
338                for (BooleanIterator it = iterator(); it.hasNext(); ) {
339                    boolean value = it.nextBoolean();
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(BooleanCollection values) {
361            checkRemoveModifiable();
362            boolean changed = false;
363            if (values != null) {
364                for (BooleanIterator it = iterator(); it.hasNext(); ) {
365                    if (values.contains(it.nextBoolean())) {
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(boolean[] values) {
385            checkRemoveModifiable();
386            boolean changed = false;
387            if (values == null || values.length == 0) {
388                changed = !isEmpty();
389                clear();
390            } else {
391                for (BooleanIterator it = iterator(); it.hasNext(); ) {
392                    boolean next = it.nextBoolean();
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(BooleanCollection values) {
420            checkRemoveModifiable();
421            boolean changed = false;
422            if (values == null || values.isEmpty()) {
423                changed = !isEmpty();
424                clear();
425            } else {
426                for (BooleanIterator it = iterator(); it.hasNext(); ) {
427                    if (values.contains(it.nextBoolean()) == 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>Boolean</code> value.
440         * <p>
441         * This implementation uses <code>contains(boolean)</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(boolean[])</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(boolean[])</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>Boolean</code>.
489         * 
490         * @return an array of <code>Boolean</code>
491         */
492        public Object[] toArray() {
493            Object[] result = new Boolean[size()];
494            BooleanIterator 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>Boolean</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<Boolean> 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>Boolean</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(boolean)</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(Boolean value) {
540            checkAddModifiable();
541            return add(toPrimitive(value));
542        }
543    
544        /**
545         * Adds a collection of <code>Boolean</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(boolean[])</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>Boolean</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 Boolean> coll) {
560            checkAddModifiable();
561            return addAll(toPrimitiveArray(coll));
562        }
563    
564        /**
565         * Removes the first occurrance of the specified <code>Boolean</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(boolean)</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>Boolean</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(boolean[])</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>Boolean</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(boolean[])</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            BooleanIterator it = iterator();
639            boolean hasNext = it.hasNext();
640            while (hasNext) {
641                buf.append(it.nextBoolean());
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, boolean[] dest, int destIndex, int size) {
664            BooleanIterator it = iterator();
665            for (int i = 0; it.hasNext() && i < size; i++) {
666                dest[destIndex + i] = it.nextBoolean();
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>boolean</code> with an Object wrapper.
721         * 
722         * @param value  the primitive value
723         * @return the Object wrapper
724         */
725        protected Boolean toObject(boolean value) {
726            return BooleanUtils.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 Boolean 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 Boolean);
739        }
740    
741        /**
742         * Unwraps the <code>Boolean</code> to retrieve the primitive <code>boolean</code>.
743         * <p>
744         * This implementation only allows non-null Boolean 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 boolean toPrimitive(Object value) {
752            return BooleanUtils.toPrimitive(value);
753        }
754    
755        /**
756         * Unwraps a <code>Collection</code> to retrieve the primitive <code>boolean</code>.
757         * <p>
758         * This implementation only allows non-null Boolean 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 boolean[] toPrimitiveArray(Collection<?> coll) {
766            return BooleanUtils.toPrimitiveArray(coll);
767        }
768    
769    }