001/*
002 * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025package Torello.Java.ReadOnly;
026
027import Torello.Java.Additional.RemoveUnsupportedIterator;
028import Torello.Java.ReadOnly.ROVectorBuilder;
029
030import java.io.IOException;
031import java.io.ObjectInputStream;
032import java.io.StreamCorruptedException;
033
034import java.util.*;
035
036import java.util.stream.Collector;
037
038import java.util.function.Consumer;
039import java.util.function.Function;
040import java.util.function.Supplier;
041import java.util.function.Predicate;
042
043/**
044 * Immutable Wrapper for <CODE>java&#46;util&#46;Vector</CODE>, found in the "Java Collections
045 * Framework".
046 * 
047 * <EMBED CLASS=globalDefs DATA-JDK=Vector>
048 * <EMBED CLASS='external-html' DATA-FILE-ID=MUCHOS_CONSTRUCTORS>
049 * <EMBED CLASS='external-html' DATA-FILE-ID=DATA_CLASS>
050 * <EMBED CLASS='external-html' DATA-FILE-ID=RO_SYNCHRONIZED>
051 *
052 * @param <E> Type of component elements
053 */
054@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="JDHBI_MAIN")
055@SuppressWarnings("unchecked")
056public class ReadOnlyVector<E>
057    // extends AbstractReadOnlyList<E>
058    implements ReadOnlyList<E>, RandomAccess, java.io.Serializable
059{
060    // ********************************************************************************************
061    // ********************************************************************************************
062    // Protected & Private Fields, Methods, Statics
063    // ********************************************************************************************
064    // ********************************************************************************************
065
066
067    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
068    protected static final long serialVersionUID = 1;
069
070    // Minor Optimization where new Vector's that have no contents always re-use this static
071    // instance.  Since this instance is completely empty, the Raw-Types things is irrelevant.
072
073    @SuppressWarnings("rawtypes")
074    private static final Vector EMPTY_VECTOR = new Vector(0);
075
076    // Singleton & Empty ReadOnlyVector, Uses the "Supplier Constructor"
077    @SuppressWarnings("rawtypes")
078    private static final ReadOnlyVector EMPTY_READONLY_VECTOR =
079        new ReadOnlyVector(0, () -> null);
080
081    // The actual Vector used by this instance.
082    private final Vector<E> vector;
083
084    // TRUE     => This was built using the class ROVectorBuilder
085    // FALSE    => This was built using the clone() of a standard java.util.Vector constructor
086
087    private final boolean fromBuilderOrVector;
088
089    // Mimics the C++ Keyword/Concept of "Friend Class".   Is "Friends With" ROVectorBuilder
090    static class AccessBadge { private AccessBadge() { } }
091    private static final AccessBadge friendClassBadge = new AccessBadge();
092
093    public static <T> ReadOnlyVector<T> emptyROV()
094    { return (ReadOnlyVector<T>) EMPTY_READONLY_VECTOR; }
095
096
097    // ********************************************************************************************
098    // ********************************************************************************************
099    // Basic Constructors
100    // ********************************************************************************************
101    // ********************************************************************************************
102
103
104    // To all the readers out there following along: The "AccessBadge" thing is just a slightly
105    // wimpier substitute for the C++ keyword / concept 'friend' or "Friend Class".  It means this
106    // constructor is (for all intents and purposes) a private-constructor, except for the class
107    // ROVectorBuilder
108    //
109    // This is the Constructor used by the Builder.  It has a "Zero-Size" Optimization
110
111    ReadOnlyVector(ROVectorBuilder<E> rovb, ROVectorBuilder.AccessBadge badge)
112    {
113        Objects.requireNonNull(badge, "Access Badge is null.  Requires Friend-Class Badge");
114
115        this.fromBuilderOrVector = true;
116        this.vector = rovb;
117    }
118
119    /**
120     * Copies parameter {@code 'c'} (and saves it) in order to guarantee that {@code 'this'}
121     * instance is Read-Only, and shielded from outside modification.
122     * 
123     * @param c The {@code Collection} to be copied and saved into this instance internal
124     * and private {@code 'vector'} field.
125     */
126    public ReadOnlyVector(Collection<E> c)
127    {
128        this.fromBuilderOrVector = false;
129
130        // Empty Optimization (throw away, completely, the reference, use static-constant)
131        this.vector = (c.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : new Vector<>(c);
132    }
133
134    /**
135     * Use a {@code Supplier<E>} to provide an arbitrary number of elements of type {@code 'E'} 
136     * directly to this constructor.  This constructor will request elements from the
137     * {@code Supplier} provided to parameter {@code 's'} until {@code 's'} returns null.
138     *
139     * @param quantityIfKnown If the number of elements to be supplied is known, that number may be
140     * provided so that the internal {@code Vector} is adequately initialized at the beginning
141     * of the constructor, without any need for resizing during construction.
142     * 
143     * <BR /><BR />If this parameter is passed null, it will be ignored.  When this happens, the
144     * initialization of the internal {@code Vector} will be done by Java's default (Zero
145     * Argument) {@code Vector}-Constructor.
146     * 
147     * <BR /><BR />It is not mandatory that the value provided be accurate, as ought be seen in the
148     * code below, this value is solely used for the {@code 'initialCapacity'} parameter to the
149     * {@code Vector} constructor.
150     * 
151     * @param s Any Java {@code Supplier<E>}
152     * 
153     * @throws IllegalArgumentException if the specified quantity / capacity is negative
154     */
155    public ReadOnlyVector(Integer quantityIfKnown, Supplier<E> s)
156    {
157        fromBuilderOrVector = false;
158
159        Vector<E>vector = (quantityIfKnown != null)
160            ? new Vector<>(quantityIfKnown)
161            : new Vector<>();
162
163        E e;
164        while ((e = s.get()) != null) vector.add(e);
165
166        // Empty Optimization (throw away, completely, the reference, use static-constant)
167        this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector;
168    }
169
170
171    // ********************************************************************************************
172    // ********************************************************************************************
173    // Iterable & Array Based Constructors - **NO FILTER**
174    // ********************************************************************************************
175    // ********************************************************************************************
176
177
178    /**
179     * If only a small amount of processing needs to be done on the contents of some Java
180     * Data-Type, and using an entire Builder-Class seems disproportionately complex - <I>this
181     * constructor can convert any Java {@code Iterable} into a {@code ReadOnlyVector}, using
182     * a simple {@code 'mapper'}</I>.
183     * 
184     * <EMBED CLASS=defs DATA-SOURCE=Iterable>
185     * 
186     * @param <T>           <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_TYPE_PARAM>
187     * @param i             Any Java {@code Iterable<T>}
188     * @param mapper        <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_MAPPER>
189     * @param sizeIfKnown   <EMBED CLASS='external-html' DATA-FILE-ID=VECAL_INIT_CAPACITY>
190     * 
191     * @throws NullPointerException If either {@code 'i'} or {@code 'mapper'} are passed null.
192     */
193    public <T> ReadOnlyVector(
194            Iterable<T>                         i,
195            Function<? super T, ? extends E>    mapper,
196            Integer                             sizeIfKnown
197        )
198    {
199        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
200
201        fromBuilderOrVector = false;
202
203        Vector<E> vector = (sizeIfKnown != null)
204            ? new Vector<>(sizeIfKnown)
205            : new Vector<>();
206
207        for (T t : i) vector.add(mapper.apply(t));
208
209        // Empty Optimization (throw away, completely, the reference, use static-constant)
210        this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector;
211    }
212
213    /**
214     * If a Standard Java {@code Iterable} can be directly mapped into a {@code Vector}
215     * (and, ergo, an entire Builder-Instance would be a bit excessive) - <I>this constructor will
216     * seamlessly convert any Java {@code Iterable<E>} directly into a {@code ReadOnlyVector<E>}
217     * with just this single invocation</I>.
218     *
219     * <EMBED CLASS=defs DATA-SOURCE=Iterable>
220     * 
221     * @param i             Any Java {@code Iteratable<E>}
222     * @param sizeIfKnown   <EMBED CLASS='external-html' DATA-FILE-ID=VECAL_INIT_CAPACITY>
223     * 
224     * @throws IllegalArgumentException if the specified initial capacity is negative
225     */
226    public ReadOnlyVector(Iterable<E> i, Integer sizeIfKnown)
227    {
228        fromBuilderOrVector = false;
229
230        Vector<E> vector = (sizeIfKnown != null)
231            ? new Vector<>(sizeIfKnown)
232            : new Vector<>();
233
234        for (E element : i) vector.add(element);
235
236        // Empty Optimization (throw away, completely, the reference, use static-constant)
237        this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector;
238    }
239
240    /**
241     * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents
242     * {@code 'elements'}.
243     * 
244     * @param elementsType  <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_TYPE>
245     * @param elements      <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
246     * 
247     * @throws ClassCastException   <EMBED CLASS='external-html' DATA-FILE-ID=CCEX>
248     * @throws NullPointerException If {@code 'elementsType'} is passed null.
249     */
250    public ReadOnlyVector(Class<E> elementsType, Object... elements)
251    {
252        Objects.requireNonNull(elementsType, ROHelpers.NULL_MSG + "'elementsType'");
253
254        fromBuilderOrVector = false;
255
256        if (elements.length == 0)
257            this.vector = (Vector<E>) EMPTY_VECTOR;
258
259        else 
260        {
261            this.vector = new Vector<>(elements.length);
262            for (Object element : elements) this.vector.add(elementsType.cast(element));
263        }
264    }
265
266    /**
267     * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents
268     * {@code 'elements'}.
269     * 
270     * @param mapper    <EMBED CLASS='external-html' DATA-FILE-ID=OBJ_E_MAPPER>
271     * @param elements  <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
272     * 
273     * @throws ClassCastException   <EMBED CLASS='external-html' DATA-FILE-ID=CCEX>
274     * @throws NullPointerException If {@code 'mapper'} is passed null.
275     */
276    public ReadOnlyVector(Function<Object, ? extends E> mapper, Object... elements)
277    {
278        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
279
280        fromBuilderOrVector = false;
281
282        if (elements.length == 0)
283            this.vector = (Vector<E>) EMPTY_VECTOR;
284
285        else 
286        {
287            this.vector = new Vector<>(elements.length);
288            for (Object element : elements) this.vector.add(mapper.apply(element));
289        }
290    }
291
292
293    // ********************************************************************************************
294    // ********************************************************************************************
295    // Iterable & Array Based Constructors - **INCLUDES ELEMENT FILTER**
296    // ********************************************************************************************
297    // ********************************************************************************************
298
299
300    /**
301     * If only a small amount of processing needs to be done on the contents of some Java
302     * Data-Type, and using an entire Builder-Class seems disproportionately complex - <I>this
303     * constructor can convert any Java {@code Iterable} into a {@code ReadOnlyVector}, using
304     * a simple {@code 'mapper'}</I>.
305     * 
306     * <EMBED CLASS=defs DATA-SOURCE=Iterable>
307     * 
308     * @param <T>           <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_TYPE_PARAM>
309     * @param i             Any Java {@code Iterable<T>}
310     * @param mapper        <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_MAPPER>
311     * @param filter        <EMBED CLASS='external-html' DATA-FTP=T DATA-FILE-ID=PREDICATE_FILTER>
312     * @param sizeIfKnown   <EMBED CLASS='external-html' DATA-FILE-ID=VECAL_INIT_CAPACITY>
313     * 
314     * @throws NullPointerException If any of {@code 'i'}, {@code 'mapper'} or {@code 'filter'} are
315     * passed null.
316     */
317    public <T> ReadOnlyVector(
318            Iterable<T>                         i,
319            Function<? super T, ? extends E>    mapper,
320            Predicate<? super T>                filter,
321            Integer                             sizeIfKnown
322        )
323    {
324        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
325        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
326
327        fromBuilderOrVector = false;
328
329        Vector<E> vector = (sizeIfKnown != null)
330            ? new Vector<>(sizeIfKnown)
331            : new Vector<>();
332
333        for (T t : i) if (filter.test(t)) vector.add(mapper.apply(t));
334
335        // Empty Optimization (throw away, completely, the reference, use static-constant)
336        this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector;
337    }
338
339    /**
340     * If a Standard Java {@code Iterable} can be directly mapped into an {@code Vector}
341     * (and, ergo, an entire Builder-Instance would be a bit excessive) - <I>this constructor will
342     * seamlessly convert any Java {@code Iterable<E>} directly into a {@code ReadOnlyVector<E>}
343     * with just this single invocation</I>.
344     *
345     * <EMBED CLASS=defs DATA-SOURCE=Iterable>
346     * 
347     * @param i             Any Java {@code Iteratable<E>}
348     * @param filter        <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER>
349     * @param sizeIfKnown   <EMBED CLASS='external-html' DATA-FILE-ID=VECAL_INIT_CAPACITY>
350     * 
351     * @throws IllegalArgumentException if the specified initial capacity is negative
352     * @throws NullPointerException     If either {@code 'i'} or {@code 'filter'} are passed null.
353     */
354    public ReadOnlyVector(Iterable<E> i, Predicate<? super E> filter, Integer sizeIfKnown)
355    {
356        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
357
358        fromBuilderOrVector = false;
359
360        Vector<E> vector = (sizeIfKnown != null)
361            ? new Vector<>(sizeIfKnown)
362            : new Vector<>();
363
364        for (E element : i) if (filter.test(element)) vector.add(element);
365
366        // Empty Optimization (throw away, completely, the reference, use static-constant)
367        this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector;
368    }
369
370    /**
371     * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents
372     * {@code 'elements'}.
373     * 
374     * @param elementsType  <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_TYPE>
375     * @param filter        <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER>
376     * @param elements      <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
377     * 
378     * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=CCEX>
379     * 
380     * @throws NullPointerException If either {@code 'elementsType'} or {@code 'filter'} are passed
381     * null.
382     */
383    public ReadOnlyVector
384        (Class<E> elementsType, Predicate<? super E> filter, Object... elements)
385    {
386        Objects.requireNonNull(elementsType, ROHelpers.NULL_MSG + "'elementsType'");
387        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
388
389        fromBuilderOrVector = false;
390
391        Vector<E> vector = new Vector<>(elements.length);
392
393        E e;
394        for (Object element : elements)
395            if (filter.test(e = elementsType.cast(element)))
396                vector.add(e);
397
398        // Empty Optimization (throw away, completely, the reference, use static-constant)
399        this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector;
400    }
401
402    /**
403     * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents
404     * {@code 'elements'}.
405     * 
406     * @param mapper    <EMBED CLASS='external-html' DATA-FILE-ID=OBJ_E_MAPPER>
407     * @param filter    <EMBED CLASS='external-html' DATA-FTP=Object DATA-FILE-ID=PREDICATE_FILTER>
408     * @param elements  <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
409     * 
410     * @throws NullPointerException If either {@code 'mapper'}  or {@code 'filter'} are passed null
411     */
412    public ReadOnlyVector(
413            Function<Object, ? extends E>   mapper,
414            Predicate<Object>               filter,
415            Object...                       elements
416        )
417    {
418        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
419        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
420
421        fromBuilderOrVector = false;
422
423        Vector<E> vector = new Vector<>(elements.length);
424
425        for (Object element : elements)
426            if (filter.test(element))
427                vector.add(mapper.apply(element));
428
429        // Empty Optimization (throw away, completely, the reference, use static-constant)
430        this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector;
431    }
432
433
434    // ********************************************************************************************
435    // ********************************************************************************************
436    // @SafeVarargs / Variable-Arity / VarArgs: with Parameterized / Generic Type's
437    // ********************************************************************************************
438    // ********************************************************************************************
439
440
441    /**
442     * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents
443     * {@code 'elements'}.
444     * 
445     * @param elements <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
446     */
447    @SafeVarargs
448    public ReadOnlyVector(E... elements)
449    {
450        fromBuilderOrVector = false;
451
452        if (elements.length == 0)
453            this.vector = (Vector<E>) EMPTY_VECTOR;
454
455        else 
456        {
457            this.vector = new Vector<>(elements.length);
458            for (E e : elements) this.vector.add(e);
459        }
460    }
461
462    /**
463     * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents
464     * {@code 'elements'}.
465     * 
466     * @param <T>       <EMBED CLASS='external-html' DATA-FILE-ID=VARARGS_TYPE_PARAM>
467     * @param dummy     <EMBED CLASS='external-html' DATA-FILE-ID=DUMMY_INT>
468     * @param mapper    <EMBED CLASS='external-html' DATA-FILE-ID=T_ARR_E_MAPPER>
469     * @param elements  <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
470     * 
471     * @throws NullPointerException If {@code 'mapper'} is null.
472     */
473    @SafeVarargs
474    public <T> ReadOnlyVector
475        (int dummy, Function<? super T, ? extends E> mapper, T... elements)
476    {
477        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
478
479        fromBuilderOrVector = false;
480
481        if (elements.length == 0)
482            this.vector = (Vector<E>) EMPTY_VECTOR;
483
484        else 
485        {
486            this.vector = new Vector<>(elements.length);
487            for (T t : elements) this.vector.add(mapper.apply(t));
488        }
489    }
490
491    /**
492     * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents
493     * {@code 'elements'}.
494     * 
495     * @param filter    <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER>
496     * @param elements  <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
497     * 
498     * @throws NullPointerException If {@code 'elementsType'} is null.
499     */
500    @SafeVarargs
501    public ReadOnlyVector(Predicate<? super E> filter, E... elements)
502    {
503        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
504
505        fromBuilderOrVector = false;
506
507        Vector<E> vector = new Vector<>(elements.length);
508        for (E e : elements) if (filter.test(e)) vector.add(e);
509
510        // Empty Optimization (throw away, completely, the reference, use static-constant)
511        this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector;
512    }
513
514    /**
515     * Builds {@code ReadOnlyVector<E>} instance having Generic-Type {@code 'E'}, and contents
516     * {@code 'elements'}.
517     * 
518     * @param <T>       <EMBED CLASS='external-html' DATA-FILE-ID=VARARGS_TYPE_PARAM>
519     * @param filter    <EMBED CLASS='external-html' DATA-FTP=T DATA-FILE-ID=PREDICATE_FILTER>
520     * @param mapper    <EMBED CLASS='external-html' DATA-FILE-ID=T_ARR_E_MAPPER>
521     * @param elements  <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
522     * 
523     * @throws NullPointerException If {@code 'mapper'} or {@code 'filter'} is null.
524     */
525    @SafeVarargs
526    public <T> ReadOnlyVector(
527            Predicate<? super T> filter,
528            Function<? super T, ? extends E> mapper,
529            T... elements
530        )
531    {
532        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
533        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
534
535        fromBuilderOrVector = false;
536
537        Vector<E> vector = new Vector<>(elements.length);
538        for (T t : elements) if (filter.test(t)) vector.add(mapper.apply(t));
539
540        // Empty Optimization (throw away, completely, the reference, use static-constant)
541        this.vector = (vector.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : vector;
542    }
543
544
545    // ********************************************************************************************
546    // ********************************************************************************************
547    // PRIMITIVE-ARRAY INPUT
548    // ********************************************************************************************
549    // ********************************************************************************************
550
551
552    /**
553     * Converts a Java Primitive-Array to a {@code ReadOnlyVector<E>}, where {@code 'E'} is the
554     * Java Boxed-Type which corresponds to the Primitive-Array's Type.
555     * 
556     * <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CTOR_DESC>
557     * @param primitiveArray        <EMBED CLASS='external-html' DATA-FILE-ID=PRIMITIVE_ARRAY>
558     * @throws ClassCastException   <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CCEX>
559     * @throws NullPointerException If {@code 'primitiveArray'} is passed null;
560     */
561    public ReadOnlyVector(Object primitiveArray)
562    {
563        fromBuilderOrVector = false;
564
565        Vector<E> v = ROHelpers.buildROListOrSet(
566            primitiveArray,
567            (int arrayLen) -> new Vector<E>(arrayLen),
568            null
569        );
570
571        // Empty Optimization (throw away, completely, the reference, use static-constant)
572        this.vector = (v.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : v;
573    }
574
575    /**
576     * Converts a Java Primitive-Array to a {@code ReadOnlyVector<E>}, where {@code 'E'} is the
577     * Java Boxed-Type which corresponds to the Primitive-Array's Type - <I>but also accepts a 
578     * {@code 'filter'} that can remove any array-entries that need to be removed</I>.
579     * 
580     * 
581     * <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CTOR_DESC>
582     * @param primitiveArray        <EMBED CLASS='external-html' DATA-FILE-ID=PRIMITIVE_ARRAY>
583     * @param filter                <EMBED CLASS='external-html' DATA-FILE-ID=PRED_FILT_PRIM>
584     * @throws ClassCastException   <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CCEX>
585     * @throws NullPointerException If {@code 'primitiveArray'} is passed null;
586     */
587    public ReadOnlyVector(
588            Object          primitiveArray,
589            Predicate<?>    filter
590        )
591    {
592        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
593
594        fromBuilderOrVector = false;
595
596        Vector<E> v = ROHelpers.buildROListOrSet(
597            primitiveArray,
598            (int arrayLen) -> new Vector<E>(arrayLen),
599            filter
600        );
601
602        // Empty Optimization (throw away, completely, the reference, use static-constant)
603        this.vector = (v.size() == 0) ? ((Vector<E>) EMPTY_VECTOR) : v;
604    }
605
606
607    // ********************************************************************************************
608    // ********************************************************************************************
609    // java.util.stream.Stream HELPER
610    // ********************************************************************************************
611    // ********************************************************************************************
612
613
614    /**
615     * For use with a the Java Stream method {@code 'collect(Collector c)'}.
616     * 
617     * <EMBED CLASS='external-html' DATA-ABBREV=v DATA-FILE-ID=STREAM_COLLECTOR>
618     * 
619     * @param <T> This is the Generic-Type of the Input-Stream.  It will also be the Generic-Type
620     * of the {@code ReadOnlyVector} that's returned from the stream's {@code collect} method.
621     * 
622     * @param characteristics Optional Characteristics List.  See Java Stream-API Documentation on
623     * {@code Collector.Characteristics} inner-class for more details.
624     * 
625     * @return This returns a collector that may be piped into a stream's {@code 'collect'} method,
626     * as in the example, above.
627     */
628    public static <T> java.util.stream.Collector
629        <T, ROVectorBuilder<T>, ReadOnlyVector<T>>
630        streamCollector(Collector.Characteristics... characteristics)
631    {
632        return Collector.of(
633            ROVectorBuilder<T>::new,    // The "Supplier"    (builds a new ROVectorBuilder)
634            ROVectorBuilder<T>::add,    // The "Accumulator" (adds elements to the builder)
635
636            // Oracle Making Life Difficult - It should be the line below, but, alas, it is not!
637            // ROVectorBuilder<T>::addAll, // The "Combiner"    (combines multiple ROVectorBuilders)
638            //
639            // In Stream.collect(), the 3rd parameter - the "combiner" - is a "BiConsumer<R, R>"
640            // NOTE: A "BiConsumer" is a FunctionalInterface that does not return anything - it is
641            // (obviously) a "void" return method!
642            //
643            // **BUT**
644            //
645            // In Collector.of, the 3rd parameter - the "combiner" - is a "BinaryOperation<R>"
646    
647            (ROVectorBuilder<T> rovb1, ROVectorBuilder<T> rovb2) ->
648            {
649                rovb1.addAll(rovb2);
650                return rovb1;
651            },
652
653            ROVectorBuilder<T>::build,  // The "Finisher"    (Converts Builder to ReadOnlyVector)
654            characteristics
655        );
656    }
657
658
659    // ********************************************************************************************
660    // ********************************************************************************************
661    // Convert to java.util Types
662    // ********************************************************************************************
663    // ********************************************************************************************
664
665
666    /**
667     * Clone's {@code 'this'} instance internal {@code Vector<E>} field, and returns it. 
668     * <EMBED CLASS='external-html' DATA-TYPE=Vector DATA-FILE-ID=CLONE_TO>
669     * 
670     * @return An independent, mutable copy of {@code 'this'} instance' internal {@code Vector<E>}
671     * data-structure.
672     */
673    public Vector<E> cloneToVector()
674    {
675        return fromBuilderOrVector
676            ? new Vector<E>(this.vector)
677            : (Vector<E>) this.vector.clone(); 
678    }
679
680    /**
681     * Invokes {@code java.util.Collections.unmodifiableList} on the internal {@code Vector}.
682     * <EMBED CLASS='external-html' DATA-RET_TYPE=List DATA-FILE-ID=WRAP_TO_IMMUTABLE>
683     * 
684     * @return A {@code List} which adheres to the JDK interface {@code java.util.List}, but throws
685     * an {@code UnsupportedOperationException} if a user attempts to invoke a Mutator-Method on
686     * the returned instance.
687     */
688    public List<E> wrapToImmutableList()
689    { return Collections.unmodifiableList(this.vector); }
690
691
692    // ********************************************************************************************
693    // ********************************************************************************************
694    // Original JDK Methods, java.util.Vectpr
695    // ********************************************************************************************
696    // ********************************************************************************************
697
698
699    /**
700     * Copies the components of this {@code Vector} into the specified array.  The item at
701     * index{@code k} in this {@code Vector} is copied into component {@code k} of {@code anArray}.
702     *
703     * @param  anArray the array into which the components get copied
704     * 
705     * @throws NullPointerException if the given array is null
706     * 
707     * @throws IndexOutOfBoundsException if the specified array is not large enough to hold all the
708     * components of this {@code Vector}
709     * 
710     * @throws ArrayStoreException if a component of this {@code Vector} is not of a runtime type
711     * that can be stored in the specified array
712     * 
713     * @see #toArray(Object[])
714     */
715    public void copyInto(Object[] anArray)
716    { this.vector.copyInto(anArray); }
717
718    /**
719     * Returns the current capacity of this {@code Vector}.
720     *
721     * @return  the current capacity (the length of its internal data array, kept in the field
722     * {@code elementData} of this {@code Vector})
723     */
724    public int capacity()
725    { return this.vector.capacity(); }
726
727    /**
728     * Returns the number of components in this {@code Vector}.
729     * 
730     * @return  the number of components in this {@code Vector}
731     */
732    public int size()
733    { return this.vector.size(); }
734
735    /**
736     * Tests if this {@code Vector} has no components.
737     *
738     * @return  {@code TRUE} if and only if this {@code Vector} has no components, that is, its
739     * size is zero; {@code FALSE} otherwise.
740     */
741    public boolean isEmpty()
742    { return this.vector.isEmpty(); }
743
744    /**
745     * Returns an enumeration of the components of this {@code Vector}. The returned
746     * {@code Enumeration} object will generate all items in this {@code Vector}. The first item
747     * generated is the item at index {@code 0}, then the item at index {@code 1}, and so on. If
748     * the {@code Vector} is structurally modified while enumerating over the elements then the
749     * results of enumerating are undefined.
750     *
751     * @return an enumeration of the components of this {@code Vector}
752     */
753    public Enumeration<E> elements()
754    { return this.vector.elements(); }
755
756    /**
757     * Returns {@code TRUE} if this {@code Vector} contains the specified element.  More formally,
758     * returns {@code TRUE} if and only if this {@code Vector} contains at least one element
759     * {@code e} such that {@code Objects.equals(o, e)}.
760     *
761     * @param o element whose presence in this {@code Vector} is to be tested
762     * 
763     * @return {@code TRUE} if this {@code Vector} contains the specified element
764     */
765    public boolean contains(Object o)
766    { return this.vector.contains(o); }
767
768    /**
769     * Returns the index of the first occurrence of the specified element in this {@code Vector},
770     * or {@code -1} if this {@code Vector} does not contain the element.  More formally, returns
771     * the lowest index {@code i} such that {@code Objects.equals(o, get(i))}, or {@code -1} if
772     * there is no such index.
773     *
774     * @param o element to search for
775     * 
776     * @return the index of the first occurrence of the specified element in this {@code Vector},
777     * or {@code -1} if this {@code Vector} does not contain the element
778     */
779    public int indexOf(Object o)
780    { return this.vector.indexOf(o); }
781
782    /**
783     * Returns the index of the first occurrence of the specified element in this {@code Vector},
784     * searching forwards from {@code index}, or returns {@code -1} if the element is not found.
785     * More formally, returns the lowest index {@code i} such that
786     * {@code (i >= index && Objects.equals(o, get(i)))}, or {@code -1} if there is no such index.
787     *
788     * @param o element to search for
789     * 
790     * @param index index to start searching from
791     * 
792     * @return the index of the first occurrence of the element in this {@code Vector} at position
793     * {@code index} or later in the {@code Vector}; {@code -1} if the element is not found.
794     * 
795     * @throws IndexOutOfBoundsException if the specified index is negative
796     */
797    public int indexOf(Object o, int index)
798    { return this.vector.indexOf(o, index); }
799
800    /**
801     * Returns the index of the last occurrence of the specified element in this {@code Vector}, or
802     * {@code -1} if this {@code Vector} does not contain the element.  More formally, returns the
803     * highest index {@code i} such that {@code Objects.equals(o, get(i))}, or {@code -1} if there
804     * is no such index.
805     *
806     * @param o element to search for
807     * 
808     * @return the index of the last occurrence of the specified element in this {@code Vector}, or
809     * {@code -1} if this {@code Vector} does not contain the element
810     */
811    public int lastIndexOf(Object o)
812    { return this.vector.lastIndexOf(o); }
813
814    /**
815     * Returns the index of the last occurrence of the specified element in this {@code Vector},
816     * searching backwards from {@code index}, or returns {@code -1} if the element is not found.
817     * More formally, returns the highest index {@code i} such that
818     * {@code (i <= index && Objects.equals(o, get(i)))}, or {@code -1} if there is no such index.
819     *
820     * @param o element to search for
821     * 
822     * @param index index to start searching backwards from
823     * 
824     * @return the index of the last occurrence of the element at position less than or equal to
825     * {@code index} in this {@code Vector}; {@code -1} if the element is not found.
826     * 
827     * @throws IndexOutOfBoundsException if the specified index is greater than or equal to the
828     * current size of this {@code Vector}
829     */
830    public int lastIndexOf(Object o, int index)
831    { return this.vector.lastIndexOf(index); }
832
833    /**
834     * Returns the component at the specified index.
835     *
836     * <BR /><BR />This method is identical in functionality to the {@link #get(int)}
837     * method (which is part of the {@link ReadOnlyList} interface).
838     *
839     * @param index an index into this {@code Vector}
840     * 
841     * @return the component at the specified index
842     * 
843     * @throws ArrayIndexOutOfBoundsException if the index is out of range
844     * ({@code index < 0 || index >= size()})
845     */
846    public E elementAt(int index)
847    { return this.vector.elementAt(index); }
848
849    /**
850     * Returns the first component (the item at index {@code 0}) of this {@code Vector}.
851     * 
852     * @return the first component of this {@code Vector}
853     * 
854     * @throws NoSuchElementException if this {@code Vector} has no components
855     */
856    public E firstElement()
857    { return this.vector.firstElement(); }
858
859    /**
860     * Returns the last component of the {@code Vector}.
861     * 
862     * @return  the last component of the {@code Vector}, i.e., the component at index
863     * {@code size() - 1}
864     * 
865     * @throws NoSuchElementException if this {@code Vector} is empty
866     */
867    public E lastElement()
868    { return this.vector.lastElement(); }
869
870    /** Returns an array containing all of the elements in this {@code Vector} in the correct order. */
871    public Object[] toArray()
872    { return this.vector.toArray(); }
873
874    /**
875     * Returns an array containing all of the elements in this {@code Vector} in the correct order;
876     * the runtime type of the returned array is that of the specified array.  If the
877     * {@code Vector} fits in the specified array, it is returned therein.  Otherwise, a new array
878     * is allocated with the runtime type of the specified array and the size of this
879     * {@code Vector}.
880     *
881     * <BR /><BR />If the {@code Vector} fits in the specified array with room to spare (i.e., the
882     * array has more elements than the {@code Vector}), the element in the array immediately
883     * following the end of the {@code Vector} is set to null.  (This is useful in determining the
884     * length of the {@code Vector} <em>only</em> if the caller knows that the {@code Vector} does
885     * not contain any null elements.)
886     *
887     * @param <T> type of array elements. The same type as {@code <E>} or a supertype of
888     * {@code <E>}.
889     * 
890     * @param a the array into which the elements of the {@code Vector} are to be stored, if it is
891     * big enough; otherwise, a new array of the same runtime type is allocated for this purpose.
892     * 
893     * @return an array containing the elements of the {@code Vector}
894     * 
895     * @throws ArrayStoreException if the runtime type of a, {@code <T>}, is not a supertype of the
896     * runtime type, {@code <E>}, of every element in this {@code Vector}
897     * 
898     * @throws NullPointerException if the given array is null
899     */
900    public <T> T[] toArray(T[] a)
901    { return this.vector.toArray(a); }
902
903    /**
904     * Returns the element at the specified position in this {@code Vector}.
905     *
906     * @param index index of the element to return
907     * 
908     * @return object at the specified index
909     * 
910     * @throws ArrayIndexOutOfBoundsException if the index is out of range
911     * ({@code index < 0 || index >= size()})
912     */
913    public E get(int index)
914    { return this.vector.get(index); }
915
916    /**
917     * Returns {@code TRUE} if this {@code Vector} contains all of the elements in the specified
918     * Collection
919     * 
920     * @param c a collection whose elements will be tested for containment in this {@code Vector}
921     * 
922     * @return {@code TRUE} if this {@code Vector} contains all of the elements in the specified
923     * collection
924     * 
925     * @throws NullPointerException if the specified collection is null
926     */
927    public boolean containsAll(Collection<?> c)
928    { return this.vector.containsAll(c); }
929
930    /**
931     * Returns a view of the portion of this List between {@code 'fromIndex'}, inclusive, and
932     * {@code 'toIndex'}, exclusive.  (If {@code 'fromIndex'} and {@code 'toIndex'} are equal, the
933     * returned List is empty.)  The returned List supports all of the optional
934     * {@code ReadOnlyList} operations supported by this {@code ReadOnlyList}.
935     *
936     * <BR /><BR />This method eliminates the need for explicit range operations (of the sort that
937     * commonly exist for arrays).  Any operation that expects a List can be used as a range
938     * operation by operating on a subList view instead of a whole List.  Idioms may be constructed
939     * for indexOf and lastIndexOf, and all of the algorithms in the Collections class can be
940     * applied to a subList.
941     *
942     * @param fromIndex low endpoint (inclusive) of the subList
943     * @param toIndex high endpoint (exclusive) of the subList
944     * @return a view of the specified range within this List
945     * 
946     * @throws IndexOutOfBoundsException if an endpoint index value is out of range
947     * {@code (fromIndex < 0 || toIndex > size)}
948     * 
949     * @throws IllegalArgumentException if the endpoint indices are out of order
950     * {@code (fromIndex > toIndex)}
951     */
952    public ReadOnlyList<E> subList(int fromIndex, int toIndex)
953    {
954        return InterfaceBuilder.toReadOnlyList(
955            fromBuilderOrVector
956                ? ((ROVectorBuilder<E>) this.vector)._subList(fromIndex, toIndex, friendClassBadge)
957                : this.vector.subList(fromIndex, toIndex)
958        );
959    }
960
961    /**
962     * Returns a list iterator over the elements in this list (in proper sequence), starting at the
963     * specified position in the list. The specified index indicates the first element that would
964     * be returned by an initial call to {@link ReadOnlyListIterator#next next}.  An initial call
965     * to {@link ReadOnlyListIterator#previous previous} would return the element with the
966     * specified index minus one.
967     *
968     * @throws IndexOutOfBoundsException if the index is out of range
969     * {@code (index < 0 || index > size())}
970     */
971    public ReadOnlyListIterator<E> listIterator(int index)
972    {
973        return InterfaceBuilder.toReadOnlyListIterator(
974            fromBuilderOrVector
975                ? ((ROVectorBuilder<E>) this.vector)._listIterator(index, friendClassBadge)
976                : this.vector.listIterator(index)
977        );
978    }
979
980    /**
981     * Returns a list iterator over the elements in this list (in proper sequence).
982     * @see #listIterator(int)
983     */
984    public ReadOnlyListIterator<E> listIterator()
985    {
986        return InterfaceBuilder.toReadOnlyListIterator(
987            fromBuilderOrVector
988                ? ((ROVectorBuilder<E>) this.vector)._listIterator(friendClassBadge)
989                : this.vector.listIterator()
990        );
991    }
992
993    /**
994     * Returns an iterator over the elements in this list in proper sequence.
995     * 
996     * @return an iterator over the elements in this list in proper sequence
997     */
998    public RemoveUnsupportedIterator<E> iterator()
999    { return new RemoveUnsupportedIterator<>(this.vector.iterator()); }
1000
1001    /** @throws NullPointerException {@inheritDoc} */
1002    @Override
1003    public void forEach(Consumer<? super E> action)
1004    { this.vector.forEach(action); }
1005
1006    /**
1007     * Uses the private and internal {@code 'vector'} field to build a {@code 'Spliterator'}
1008     * @return a {@code Spliterator} over the elements in this list
1009     */
1010    @Override
1011    public Spliterator<E> spliterator()
1012    { return this.vector.spliterator(); }
1013
1014
1015    // ********************************************************************************************
1016    // ********************************************************************************************
1017    // java.lang.Object
1018    // ********************************************************************************************
1019    // ********************************************************************************************
1020
1021
1022    /**
1023     * Returns a {@code String} representation of this {@code Vector}. The {@code String}
1024     * representation consists of a list of the collection's elements in the order they are
1025     * returned by its iterator, enclosed in square brackets ({@code "[]"}). Adjacent elements are
1026     * separated by the characters {@code ", "} (comma and space). Elements are converted to
1027     * {@code String's} as by {@code String.valueOf(Object)}.
1028     * 
1029     * @return a {@code String} representation of this {@code Vector}
1030     */
1031    public String toString()
1032    { return this.vector.toString(); }
1033
1034    /**
1035     * Compares the specified Object with this List for equality, as per the definition in the 
1036     * class {@code java.util.Vector}.
1037     *
1038     * @param  o object to be compared for equality with this {@code ReadOnlyVector}.
1039     * @return {@code TRUE} if the specified Object is equal to this list
1040     */
1041    public boolean equals(Object o)
1042    { return ROHelpers.roListEq(this, o); }
1043
1044    /**
1045     * Returns the hash code value for this List as per the definition in the class
1046     * {@code java.util.Vector}.
1047     */
1048    public int hashCode() 
1049    { return this.vector.hashCode(); }
1050}
1051