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.ByteUtils;
023import org.joda.primitives.collection.ByteCollection;
024import org.joda.primitives.iterator.ByteIterator;
025
026/**
027 * Abstract base class for collections of primitive <code>byte</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(byte)</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 AbstractByteCollection
043        extends AbstractPrimitiveCollectable<Byte>
044        implements ByteCollection {
045    // This file is CODE GENERATED. Do not change manually.
046
047    /**
048     * Constructor.
049     */
050    protected AbstractByteCollection() {
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>byteIterator()</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(byte value) {
065        for (ByteIterator it = iterator(); it.hasNext();) {
066            if (it.nextByte() == 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(byte)</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(byte[] 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(byte)</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(ByteCollection values) {
103        if (values != null) {
104            for (ByteIterator it = values.iterator(); it.hasNext(); ) {
105                if (contains(it.nextByte()) == false) {
106                    return false;
107                }
108            }
109        }
110        return true;
111    }
112
113    /**
114     * Checks if this collection contain all the values in the specified range.
115     * <p>
116     * The range is defined to be inclusive of the start and end.
117     * If the start is greater than the end then the result is <code>true</code>
118     * as the range is equivalent to an empty collection.
119     * <p>
120     * This implementation uses <code>contains(byte)</code>.
121     *
122     * @param startInclusive  the inclusive range start value
123     * @param endInclusive  the inclusive range end value
124     * @return <code>true</code> if the collection contains the entire range
125     */
126    public boolean containsAll(byte startInclusive, byte endInclusive) {
127        if (startInclusive > endInclusive) {
128            return true;
129        }
130        for (byte i = startInclusive; i <= endInclusive; i++) {
131            if (contains(i) == false) {
132                return false;
133            }
134        }
135        return true;
136    }
137
138    /**
139     * Checks if this collection contains any of the values in the specified array.
140     * If the specified array is empty, <code>false</code> is returned.
141     * <p>
142     * This implementation uses <code>contains(byte)</code>.
143     *
144     * @param values  the values to search for, null treated as empty array
145     * @return <code>true</code> if at least one of the values is found
146     */
147    public boolean containsAny(byte[] values) {
148        if (values != null) {
149            for (int i = 0; i < values.length; i++) {
150                if (contains(values[i])) {
151                    return true;
152                }
153            }
154        }
155        return false;
156    }
157
158    /**
159     * Checks if this collection contains any of the values in the specified collection.
160     * If the specified collection is empty, <code>false</code> is returned.
161     * <p>
162     * This implementation uses <code>contains(byte)</code>.
163     *
164     * @param values  the values to search for, null treated as empty collection
165     * @return <code>true</code> if at least one of the values is found
166     */
167    public boolean containsAny(ByteCollection values) {
168        if (values != null) {
169            for (ByteIterator it = values.iterator(); it.hasNext(); ) {
170                if (contains(it.nextByte())) {
171                    return true;
172                }
173            }
174        }
175        return false;
176    }
177
178    /**
179     * Checks if this collection contain some of the values in the specified range.
180     * <p>
181     * The range is defined to be inclusive of the start and end.
182     * If the start is greater than the end then the result is <code>false</code>
183     * as the range is equivalent to an empty collection.
184     * <p>
185     * This implementation uses <code>contains(byte)</code>.
186     *
187     * @param startInclusive  the inclusive range start value
188     * @param endInclusive  the inclusive range end value
189     * @return <code>true</code> if the collection contains at least one of the range
190     */
191    public boolean containsAny(byte startInclusive, byte endInclusive) {
192        if (startInclusive > endInclusive) {
193            return false;
194        }
195        for (byte i = startInclusive; i <= endInclusive; i++) {
196            if (contains(i)) {
197                return true;
198            }
199        }
200        return false;
201    }
202
203    /**
204     * Gets the elements of this collection as an array.
205     * <p>
206     * This implementation uses <code>arrayCopy</code>.
207     *
208     * @return a new array containing a copy of the elements of this collection
209     */
210    public byte[] toByteArray() {
211        if (size() == 0) {
212            return ByteUtils.EMPTY_BYTE_ARRAY;
213        }
214        byte[] result = new byte[size()];
215        arrayCopy(0, result, 0, size());
216        return result;
217    }
218
219    /**
220     * Copies the elements of this collection into an array at a specified position.
221     * Previous values in the array are overwritten.
222     * <p>
223     * If the array specified is null a new array is created.
224     * If the array specified is large enough, it will be modified.
225     * If the array is not large enough, a new array will be created containing the
226     * values from the specified array before the startIndex plus those from this collection.
227     * <p>
228     * This implementation uses <code>arrayCopy</code>.
229     *
230     * @param array  the array to add the elements to, null treated as empty array
231     * @param startIndex  the position in the array to start setting elements
232     * @return the array with the populated collection
233     * @throws IndexOutOfBoundsException if the index is negative
234     */
235    public byte[] toByteArray(byte[] array, int startIndex) {
236        if (startIndex < 0) {
237            throw new IndexOutOfBoundsException("Start index must not be negative: " + startIndex);
238        }
239        byte[] result = null;
240        if (array == null) {
241            // create new
242            result = new byte[startIndex + size()];
243            
244        } else if (array.length - startIndex - size() >= 0) {
245            // room to fit data
246            result = array;
247            
248        } else {
249            // expand array
250            result = new byte[startIndex + size()];
251            System.arraycopy(array, 0, result, 0, startIndex);
252        }
253        arrayCopy(0, result, startIndex, size());
254        return result;
255    }
256
257    // Optional operations
258    //-----------------------------------------------------------------------
259    /**
260     * Clears the collection/map of all elements (optional operation).
261     * <p>
262     * The collection/map will have a zero size after this method completes.
263     * This method is optional, throwing an UnsupportedOperationException if the
264     * collection/map cannot be cleared.
265     * <p>
266     * This implementation uses <code>iterator()</code>.
267     *
268     * @throws UnsupportedOperationException if method not supported by this collection
269     */
270    public void clear() {
271        checkRemoveModifiable();
272        for (ByteIterator it = iterator(); it.hasNext();) {
273            it.nextByte();
274            it.remove();
275        }
276    }
277
278    /**
279     * Adds a primitive value to this collection (optional operation).
280     * <p>
281     * This implementation throws UnsupportedOperationException.
282     *
283     * @param value  the value to add to this collection
284     * @return <code>true</code> if this collection was modified by this method call
285     * @throws IllegalArgumentException if value is rejected by this collection
286     * @throws UnsupportedOperationException if not supported by this collection
287     */
288    public boolean add(byte value) {
289        throw new UnsupportedOperationException("Collection does not support add");
290    }
291
292    /**
293     * Adds an array of primitive values to this collection (optional operation).
294     * <p>
295     * This implementation uses <code>add(byte)</code>.
296     *
297     * @param values  the values to add to this collection, null treated as empty array
298     * @return <code>true</code> if this collection was modified by this method call
299     * @throws IllegalArgumentException if a value is rejected by this collection
300     * @throws UnsupportedOperationException if not supported by this collection
301     */
302    public boolean addAll(byte[] values) {
303        checkAddModifiable();
304        boolean changed = false;
305        if (values != null) {
306            for (int i = 0; i < values.length; i++) {
307                changed |= add(values[i]);
308            }
309        }
310        return changed;
311    }
312
313    /**
314     * Adds a collection of primitive values to this collection (optional operation).
315     * <p>
316     * This implementation uses <code>add(byte)</code>.
317     *
318     * @param values  the values to add to this collection, null treated as empty collection
319     * @return <code>true</code> if this collection was modified by this method call
320     * @throws IllegalArgumentException if a value is rejected by this collection
321     * @throws UnsupportedOperationException if not supported by this collection
322     */
323    public boolean addAll(ByteCollection values) {
324        checkAddModifiable();
325        boolean changed = false;
326        if (values != null) {
327            for (ByteIterator it = values.iterator(); it.hasNext(); ) {
328                changed |= add(it.nextByte());
329            }
330        }
331        return changed;
332    }
333
334    /**
335     * Adds a range of primitive values to this collection (optional operation).
336     * <p>
337     * The range is defined to be inclusive of the start and end.
338     * If the start is greater than the end then the range is equivalent to an empty collection.
339     * <p>
340     * This implementation uses <code>add(byte)</code>.
341     *
342     * @param startInclusive  the inclusive range start value
343     * @param endInclusive  the inclusive range end value
344     * @return <code>true</code> if this collection was modified by this method call
345     * @throws IllegalArgumentException if a value is rejected by this set
346     * @throws UnsupportedOperationException if not supported by this set
347     */
348    public boolean addAll(byte startInclusive, byte endInclusive) {
349        checkAddModifiable();
350        if (startInclusive > endInclusive) {
351            return false;
352        }
353        boolean changed = false;
354        for (byte i = startInclusive; i <= endInclusive; i++) {
355            changed |= add(i);
356        }
357        return false;
358    }
359
360    /**
361     * Removes the first occurrence of the specified primitive value from this collection
362     * <p>
363     * This implementation uses <code>iterator().remove()</code>.
364     *
365     * @param value  the value to remove
366     * @return <code>true</code> if this collection was modified by this method call
367     * @throws UnsupportedOperationException if not supported by this collection
368     */
369    public boolean removeFirst(byte value) {
370        checkRemoveModifiable();
371        for (ByteIterator it = iterator(); it.hasNext(); ) {
372            if (it.nextByte() == value) {
373                it.remove();
374                return true;
375            }
376        }
377        return false;
378    }
379
380    /**
381     * Removes all occurrences of the specified primitive value from this collection.
382     * <p>
383     * This implementation uses <code>iterator().remove()</code>.
384     *
385     * @param value  the value to remove
386     * @return <code>true</code> if this collection was modified by this method call
387     * @throws UnsupportedOperationException if not supported by this collection
388     */
389    public boolean removeAll(byte value) {
390        checkRemoveModifiable();
391        boolean changed = false;
392        for (ByteIterator it = iterator(); it.hasNext(); ) {
393            if (it.nextByte() == value) {
394                it.remove();
395                changed = true;
396            }
397        }
398        return changed;
399    }
400
401    /**
402     * Removes all occurrences from this collection of each primitive in the specified array.
403     * <p>
404     * This implementation uses <code>iterator().remove()</code>.
405     *
406     * @param values  the values to remove from this collection, null treated as empty array
407     * @return <code>true</code> if this list was modified by this method call
408     * @throws UnsupportedOperationException if not supported by this collection
409     */
410    public boolean removeAll(byte[] values) {
411        checkRemoveModifiable();
412        boolean changed = false;
413        if (values != null) {
414            for (ByteIterator it = iterator(); it.hasNext(); ) {
415                byte value = it.nextByte();
416                for (int i = 0; i < values.length; i++) {
417                    if (values[i] == value) {
418                        it.remove();
419                        changed = true;
420                    }
421                }
422            }
423        }
424        return changed;
425    }
426
427    /**
428     * Removes all occurrences from this collection of each primitive in the specified collection.
429     * <p>
430     * This implementation uses <code>iterator().remove()</code>.
431     *
432     * @param values  the values to remove from this collection, null treated as empty collection
433     * @return <code>true</code> if this list was modified by this method call
434     * @throws UnsupportedOperationException if not supported by this collection
435     */
436    public boolean removeAll(ByteCollection values) {
437        checkRemoveModifiable();
438        boolean changed = false;
439        if (values != null) {
440            for (ByteIterator it = iterator(); it.hasNext(); ) {
441                if (values.contains(it.nextByte())) {
442                    it.remove();
443                    changed = true;
444                }
445            }
446        }
447        return changed;
448    }
449
450    /**
451     * Removes all occurrences of a range of primitive values from this collection.
452     * <p>
453     * The range is defined to be inclusive of the start and end.
454     * The elements removed are greater than or equal to the start and
455     * less than or equal to the end. Thus if the start is greater than the
456     * end then no elements are removed.
457     * <p>
458     * This method is optional, throwing an UnsupportedOperationException if the
459     * set cannot be changed.
460     * <p>
461     * This implementation uses <code>iterator().remove()</code>.
462     *
463     * @param startInclusive  the inclusive range start value
464     * @param endInclusive  the inclusive range end value
465     * @return <code>true</code> if this collection was modified by this method call
466     * @throws UnsupportedOperationException if not supported by this collection
467     */
468    public boolean removeAll(byte startInclusive, byte endInclusive) {
469        checkRemoveModifiable();
470        if (startInclusive > endInclusive) {
471            return false;
472        }
473        boolean changed = false;
474        for (ByteIterator it = iterator(); it.hasNext(); ) {
475            byte value = it.nextByte();
476            if (value >= startInclusive && value <= endInclusive) {
477                it.remove();
478                changed = true;
479            }
480        }
481        return changed;
482    }
483
484    /**
485     * Retains each element of this collection that is present in the specified array
486     * removing all other values.
487     * <p>
488     * This implementation uses <code>iterator().remove()</code>.
489     *
490     * @param values  the values to remove from this collection, null treated as empty array
491     * @return <code>true</code> if this list was modified by this method call
492     * @throws UnsupportedOperationException if not supported by this collection
493     */
494    public boolean retainAll(byte[] values) {
495        checkRemoveModifiable();
496        boolean changed = false;
497        if (values == null || values.length == 0) {
498            changed = !isEmpty();
499            clear();
500        } else {
501            for (ByteIterator it = iterator(); it.hasNext(); ) {
502                byte next = it.nextByte();
503                boolean match = false;
504                for (int i = 0; i < values.length; i++) {
505                    if (values[i] == next) {
506                        match = true;
507                        break;
508                    }
509                }
510                if (match == false) {
511                    it.remove();
512                    changed = true;
513                }
514            }
515        }
516        return changed;
517    }
518
519    /**
520     * Retains each element of this collection that is present in the specified collection
521     * removing all other values.
522     * <p>
523     * This implementation uses <code>iterator().remove()</code>.
524     *
525     * @param values  the values to retain in this collection, null treated as empty collection
526     * @return <code>true</code> if this collection was modified by this method call
527     * @throws UnsupportedOperationException if not supported by this collection
528     */
529    public boolean retainAll(ByteCollection values) {
530        checkRemoveModifiable();
531        boolean changed = false;
532        if (values == null || values.isEmpty()) {
533            changed = !isEmpty();
534            clear();
535        } else {
536            for (ByteIterator it = iterator(); it.hasNext(); ) {
537                if (values.contains(it.nextByte()) == false) {
538                    it.remove();
539                    changed = true;
540                }
541            }
542        }
543        return changed;
544    }
545
546    /**
547     * Retains all occurences of a range of primitive values within this collection
548     * removing all values outside the range (optional operation).
549     * <p>
550     * The range is defined to be inclusive of the start and end.
551     * If the start is greater than the end then the range is equivalent to an empty collection.
552     * <p>
553     * This method is optional, throwing an UnsupportedOperationException if the
554     * set cannot be changed.
555     *
556     * @param startInclusive  the inclusive range start value
557     * @param endInclusive  the inclusive range end value
558     * @return <code>true</code> if this collection was modified by this method call
559     * @throws UnsupportedOperationException if not supported by this collection
560     */
561    public boolean retainAll(byte startInclusive, byte endInclusive) {
562        checkRemoveModifiable();
563        boolean changed = false;
564        for (ByteIterator it = iterator(); it.hasNext(); ) {
565            byte value = it.nextByte();
566            if (value < startInclusive || value > endInclusive) {
567                it.remove();
568                changed = true;
569            }
570        }
571        return changed;
572    }
573
574    // Collection integration
575    //-----------------------------------------------------------------------
576    /**
577     * Checks whether this collection contains a specified <code>Byte</code> value.
578     * <p>
579     * This implementation uses <code>contains(byte)</code>.
580     *
581     * @param value  the value to search for
582     * @return <code>true</code> if the value is found
583     */
584    public boolean contains(Object value) {
585        return contains(toPrimitive(value));
586    }
587
588    /**
589     * Checks if the collection contains all of the primitive values.
590     * <p>
591     * This implementation uses <code>containsAll(byte[])</code>.
592     *
593     * @param coll  the collection of values to search for
594     * @return <code>true</code> if all the values are found
595     */
596    public boolean containsAll(Collection<?> coll) {
597        if (coll == this || coll.size() == 0) {
598            return true;
599        }
600        if (size() == 0) {
601            return false;
602        }
603        return containsAll(toPrimitiveArray(coll));
604    }
605
606    /**
607     * Checks if the collection contains any of the primitive values in the array.
608     * If the specified collection is empty, <code>false</code> is returned.
609     * <p>
610     * This implementation uses <code>containsAny(byte[])</code>.
611     *
612     * @param coll  the collection of values to search for
613     * @return <code>true</code> if at least one of the values is found
614     */
615    public boolean containsAny(Collection<?> coll) {
616        if (size() == 0 || coll.size() == 0) {
617            return false;
618        }
619        if (coll == this) {
620            return true;
621        }
622        return containsAny(toPrimitiveArray(coll));
623    }
624
625    /**
626     * Gets the collection as an array of <code>Byte</code>.
627     * 
628     * @return an array of <code>Byte</code>
629     */
630    public Object[] toArray() {
631        Object[] result = new Byte[size()];
632        ByteIterator it = iterator();
633        for (int i = 0; it.hasNext(); i++) {
634            result[i] = it.next();
635        }
636        return result;
637    }
638
639    /**
640     * Gets the collection as an array, using the array provided.
641     * 
642     * @param array  the array to populate
643     * @return an array of <code>Byte</code>
644     */
645    @SuppressWarnings("unchecked")
646    public <T> T[] toArray(T[] array) {
647        int size = size();
648        if (array.length < size) {
649          array = (T[]) Array.newInstance(array.getClass().getComponentType(), size);
650        }
651
652        Iterator<Byte> it = iterator();
653        for (int i = 0; i < size; i++) {
654            array[i] = (T)it.next();
655        }
656
657        if (array.length > size) {
658            array[size] = null;
659        }
660        
661        return array;
662    }
663
664    /**
665     * Adds the <code>Byte</code> value to this collection (optional operation).
666     * <p>
667     * This method is optional, throwing an UnsupportedOperationException if the
668     * collection cannot be added to.
669     * <p>
670     * This implementation uses <code>add(byte)</code>.
671     *
672     * @param value  the value to add to this collection
673     * @return <code>true</code> if this collection was modified by this method call
674     * @throws IllegalArgumentException if value is rejected by this collection
675     * @throws UnsupportedOperationException if not supported by this collection
676     */
677    public boolean add(Byte value) {
678        checkAddModifiable();
679        return add(toPrimitive(value));
680    }
681
682    /**
683     * Adds a collection of <code>Byte</code> values to this collection (optional operation).
684     * <p>
685     * This method is optional, throwing an UnsupportedOperationException if the
686     * collection cannot be added to.
687     * <p>
688     * This implementation uses <code>addAll(byte[])</code>.
689     *
690     * @param coll  the values to add to this collection
691     * @return <code>true</code> if this list was modified by this method call
692     * @throws IndexOutOfBoundsException if the index is invalid
693     * @throws ClassCastException if any object is not <code>Byte</code>
694     * @throws IllegalArgumentException if value is rejected by this collection
695     * @throws UnsupportedOperationException if not supported by this collection
696     */
697    public boolean addAll(Collection<? extends Byte> coll) {
698        checkAddModifiable();
699        return addAll(toPrimitiveArray(coll));
700    }
701
702    /**
703     * Removes the first occurrance of the specified <code>Byte</code> value from
704     * this collection (optional operation).
705     * <p>
706     * This method is optional, throwing an UnsupportedOperationException if the
707     * collection cannot be removed from.
708     * <p>
709     * This implementation uses <code>removeFirst(byte)</code>.
710     *
711     * @param value  the value to remove
712     * @return <code>true</code> if this collection was modified by this method call
713     * @throws UnsupportedOperationException if not supported by this collection
714     */
715    public boolean remove(Object value) {
716        checkRemoveModifiable();
717        return removeFirst(toPrimitive(value));
718    }
719
720    /**
721     * Removes each of a collection of <code>Byte</code> values from this collection (optional operation).
722     * <p>
723     * This method is optional, throwing an UnsupportedOperationException if the
724     * collection cannot be added to.
725     * <p>
726     * This implementation uses <code>removeAll(byte[])</code>.
727     *
728     * @param coll  the values to remove from this collection
729     * @return <code>true</code> if this list was modified by this method call
730     * @throws UnsupportedOperationException if not supported by this collection
731     */
732    public boolean removeAll(Collection<?> coll) {
733        checkRemoveModifiable();
734        if (coll == this) {
735            int size = size();
736            clear();
737            return (size() != size);
738        }
739        return removeAll(toPrimitiveArray(coll));
740    }
741
742    /**
743     * Retains each of a collection of <code>Byte</code> values, removing other
744     * values (optional operation).
745     * <p>
746     * This method is optional, throwing an UnsupportedOperationException if the
747     * collection cannot be added to.
748     * <p>
749     * This implementation uses <code>retainAll(byte[])</code>.
750     *
751     * @param coll  the values to retain in this collection
752     * @return <code>true</code> if this list was modified by this method call
753     * @throws UnsupportedOperationException if not supported by this collection
754     */
755    public boolean retainAll(Collection<?> coll) {
756        checkRemoveModifiable();
757        if (coll == this) {
758            return false;
759        }
760        return retainAll(toPrimitiveArray(coll));
761    }
762
763    // Basics
764    //-----------------------------------------------------------------------
765    /**
766     * Gets a string representing this collection.
767     * <p>
768     * The format used is as per <code>Collection</code>.
769     * 
770     * @return collection as a String
771     */
772    public String toString() {
773        StringBuffer buf = new StringBuffer();
774        buf.append("[");
775
776        ByteIterator it = iterator();
777        boolean hasNext = it.hasNext();
778        while (hasNext) {
779            buf.append(it.nextByte());
780            hasNext = it.hasNext();
781            if (hasNext) {
782                buf.append(", ");
783            }
784        }
785
786        buf.append("]");
787        return buf.toString();
788    }
789    
790    // Internals
791    //-----------------------------------------------------------------------
792    /**
793     * Copies data from this collection into the specified array.
794     * This method is pre-validated.
795     * 
796     * @param fromIndex  the index to start from
797     * @param dest  the destination array
798     * @param destIndex  the destination start index
799     * @param size  the number of items to copy
800     */
801    protected void arrayCopy(int fromIndex, byte[] dest, int destIndex, int size) {
802        ByteIterator it = iterator();
803        for (int i = 0; it.hasNext() && i < size; i++) {
804            dest[destIndex + i] = it.nextByte();
805        }
806    }
807
808    /**
809     * Are the add methods supported.
810     * <p>
811     * This implementation returns false.
812     *
813     * @return true if supported
814     */
815    protected boolean isAddModifiable() {
816        return false;
817    }
818
819    /**
820     * Are the remove methods supported.
821     * <p>
822     * This implementation returns false.
823     *
824     * @return true if supported
825     */
826    protected boolean isRemoveModifiable() {
827        return false;
828    }
829
830    /**
831     * Is the collection modifiable in any way.
832     *
833     * @return true if supported
834     */
835    public boolean isModifiable() {
836        return isAddModifiable() || isRemoveModifiable();
837    }
838
839    /**
840     * Check whether add is suported and throw an exception.
841     */
842    protected void checkAddModifiable() {
843        if (isAddModifiable() == false) {
844            throw new UnsupportedOperationException("Collection does not support add");
845        }
846    }
847
848    /**
849     * Check whether remove is suported and throw an exception.
850     */
851    protected void checkRemoveModifiable() {
852        if (isRemoveModifiable() == false) {
853            throw new UnsupportedOperationException("Collection does not support remove");
854        }
855    }
856
857    /**
858     * Wraps an <code>byte</code> with an Object wrapper.
859     * 
860     * @param value  the primitive value
861     * @return the Object wrapper
862     */
863    protected Byte toObject(byte value) {
864        return ByteUtils.toObject(value);
865    }
866
867    /**
868     * Checks if the object can be converted to a primitive successfully.
869     * <p>
870     * This implementation only allows non-null Byte objects.
871     * 
872     * @param value  the Object wrapper
873     * @return true if a primitive value can be successfully extracted
874     */
875    protected boolean isToPrimitivePossible(Object value) {
876        return (value instanceof Byte);
877    }
878
879    /**
880     * Unwraps the <code>Byte</code> to retrieve the primitive <code>byte</code>.
881     * <p>
882     * This implementation only allows non-null Byte objects.
883     * 
884     * @param value  the Object to convert to a primitive
885     * @return the primitive value
886     * @throws NullPointerException if the value is null and this is unacceptable
887     * @throws ClassCastException if the object is of an unsuitable type
888     */
889    protected byte toPrimitive(Object value) {
890        return ByteUtils.toPrimitive(value);
891    }
892
893    /**
894     * Unwraps a <code>Collection</code> to retrieve the primitive <code>byte</code>.
895     * <p>
896     * This implementation only allows non-null Byte objects.
897     * 
898     * @param coll  the Collection to convert to primitives
899     * @return the primitive value
900     * @throws NullPointerException if the value is null and this is unacceptable
901     * @throws ClassCastException if any object is of an unsuitable type
902     */
903    protected byte[] toPrimitiveArray(Collection<?> coll) {
904        return ByteUtils.toPrimitiveArray(coll);
905    }
906
907}