001/*
002 * Copyright (c) 1998, 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;
028
029import java.util.*;
030
031import java.io.Serializable;
032
033import java.util.stream.Collector;
034
035import java.util.function.Function;
036import java.util.function.Supplier;
037import java.util.function.Predicate;
038
039/**
040 * Immutable Wrapper for <CODE>java&#46;util&#46;TreeSet</CODE>, found in the "Java Collections
041 * Framework".
042 * 
043 * <EMBED CLASS=globalDefs DATA-JDK=TreeSet>
044 * <EMBED CLASS='external-html' DATA-FILE-ID=MUCHOS_CONSTRUCTORS>
045 * <EMBED CLASS='external-html' DATA-FILE-ID=DATA_CLASS>
046 * 
047 * @param <E> the type of elements maintained by this set
048 */
049@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="JDHBI_MAIN")
050@SuppressWarnings("unchecked")
051public class ReadOnlyTreeSet<E>
052    // extends AbstractReadOnlySet<E>
053    implements ReadOnlyNavigableSet<E>, Serializable
054{
055    // ********************************************************************************************
056    // ********************************************************************************************
057    // Protected & Private Fields, Methods, Statics
058    // ********************************************************************************************
059    // ********************************************************************************************
060
061
062    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
063    protected static final long serialVersionUID = 1;
064
065    // Minor Optimization where new TreeSet's that have no contents always re-use this static
066    // instance.  Since this instance is completely empty, the Raw-Types things is irrelevant.
067
068    @SuppressWarnings("rawtypes")
069    private static final TreeSet EMPTY_TREE_SET = new TreeSet();
070
071    // Singleton & Empty ReadOnlyTreeSet, Uses the "Supplier Constructor"
072    @SuppressWarnings("rawtypes")
073    private static final ReadOnlyTreeSet EMPTY_READONLY_TREE_SET =
074        new ReadOnlyTreeSet(null, () -> null);
075
076    // The actual TreeSet used by this instance.
077    private final TreeSet<E> treeSet;
078
079    // TRUE     => This was built using the class ROTreeSetBuilder
080    // FALSE    => This was built using the clone() of a standard java.util.TreeSet constructor
081
082    private final boolean fromBuilderOrTreeSet;
083
084    // Mimics the C++ Keyword/Concept of "Friend Class".   Is "Friends With" ROTreeSetBuilder
085    static class AccessBadge { private AccessBadge() { } }
086    private static final AccessBadge friendClassBadge = new AccessBadge();
087
088    public static <T> ReadOnlyTreeSet<T> emptyROTS()
089    { return (ReadOnlyTreeSet<T>) EMPTY_READONLY_TREE_SET; }
090
091
092    // ********************************************************************************************
093    // ********************************************************************************************
094    // Basic Constructors
095    // ********************************************************************************************
096    // ********************************************************************************************
097
098
099    // To all the readers out there following along: The "AccessBadge" thing is just a slightly
100    // wimpier substitute for the C++ keyword / concept 'friend' or "Friend Class".  It means this
101    // constructor is (for all intents and purposes) a private-constructor, except for the class
102    // ROTreeSetBuilder
103    //
104    // This is the Constructor used by the Builder.  It has a "Zero-Size" Optimization
105
106    ReadOnlyTreeSet(ROTreeSetBuilder<E> rotsb, ROTreeSetBuilder.AccessBadge badge)
107    {
108        Objects.requireNonNull(badge, "Access Badge is null.  Requires Friend-Class Badge");
109
110        fromBuilderOrTreeSet = true;
111        this.treeSet = rotsb;
112    }
113
114    /**
115     * Copies parameter {@code 'c'} (and saves it) in order to guarantee that {@code 'this'}
116     * instance is Read-Only, and shielded from outside modification.
117     * 
118     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
119     * 
120     * @param c The {@code TreeSet} to be copied and saved into this instance internal
121     * and private {@code 'treeSet'} field.
122     */
123    public ReadOnlyTreeSet(Collection<E> c)
124    {
125        fromBuilderOrTreeSet = false;
126        this.treeSet = (c.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : new TreeSet<>(c);
127    }
128
129    /**
130     * Copies parameter {@code 's'} (and saves it) in order to guarantee that {@code 'this'}
131     * instance is Read-Only, and shielded from outside modification.
132     * 
133     * @param s The {@code TreeSet} to be copied and saved into this instance internal
134     * and private {@code 'treeSet'} field.
135     */
136    public ReadOnlyTreeSet(SortedSet<E> s)
137    {
138        fromBuilderOrTreeSet = false;
139        this.treeSet = (s.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : new TreeSet<>(s);
140    }
141
142    /**
143     * Use a {@code Supplier<E>} to provide an arbitrary number of elements of type {@code 'E'} 
144     * directly to this constructor.  This constructor will request elements from the
145     * {@code Supplier} provided to parameter {@code 's'} until {@code 's'} returns null.
146     *
147     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
148     * 
149     * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
150     * @param s Any Java {@code Supplier<E>}
151     */
152    public ReadOnlyTreeSet(Comparator<? super E> comparator, Supplier<E> s)
153    {
154        fromBuilderOrTreeSet = false;
155
156        TreeSet<E> treeSet = (comparator != null)
157            ? new TreeSet<>(comparator)
158            : new TreeSet<>();
159
160        E e;
161        while ((e = s.get()) != null) treeSet.add(e);
162
163        // Empty Optimization (throw away, completely, the reference, use static-constant)
164        this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet;
165    }
166
167
168    // ********************************************************************************************
169    // ********************************************************************************************
170    // Iterable & Array Based Constructors - **NO FILTER**
171    // ********************************************************************************************
172    // ********************************************************************************************
173
174
175    /**
176     * If only a small amount of processing needs to be done on the contents of some Java
177     * Data-Type, and using an entire Builder-Class seems disproportionately complex - <I>this
178     * constructor can convert any Java {@code Iterable} into a {@code ReadOnlyTreeSet}, using
179     * a simple {@code 'mapper'}</I>.
180     * 
181     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
182     * 
183     * @param <T>        <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_TYPE_PARAM>
184     * @param i          Any Java {@code Iterable}
185     * @param mapper     <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_MAPPER>
186     * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
187     * 
188     * @throws NullPointerException if either {@code 'i'} or {@code 'mapper'} are passed null.
189     */
190    public <T> ReadOnlyTreeSet(
191            Iterable<T> i,
192            Function<? super T, ? extends E> mapper,
193            Comparator<? super E> comparator
194        )
195    {
196        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
197
198        fromBuilderOrTreeSet = false;
199
200        TreeSet<E> treeSet = (comparator != null)
201            ? new TreeSet<>(comparator)
202            : new TreeSet<>();
203
204        for (T t : i) treeSet.add(mapper.apply(t));
205
206        // Empty Optimization (throw away, completely, the reference, use static-constant)
207        this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet;
208    }
209
210    /**
211     * If a Standard Java {@code Iterable} can be directly mapped into a {@code TreeSet}
212     * (and, ergo, an entire Builder-Instance would be a bit excessive) - <I>this constructor will
213     * seamlessly convert any Java {@code Iterable<E>} directly into a {@code ReadOnlyTreeSet<E>}
214     * with just this single invocation</I>.
215     * 
216     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
217     * 
218     * @param i             Any Java {@code Iterable<E>}
219     * @param comparator    <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
220     */
221    public ReadOnlyTreeSet(Iterable<E> i, Comparator<? super E> comparator)
222    {
223        fromBuilderOrTreeSet = false;
224
225        TreeSet<E> treeSet = (comparator != null)
226            ? new TreeSet<>(comparator)
227            : new TreeSet<>();
228
229        for (E element : i) treeSet.add(element);
230
231        // Empty Optimization (throw away, completely, the reference, use static-constant)
232        this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet;
233    }
234
235    /**
236     * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents
237     * {@code 'elements'}.
238     * 
239     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
240     * 
241     * @param elementsType  <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_TYPE>
242     * @param comparator    <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
243     * @param elements      <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
244     * 
245     * @throws ClassCastException   <EMBED CLASS='external-html' DATA-FILE-ID=CCEX>
246     * @throws NullPointerException If {@code 'elementsType'} is passed null.
247     */
248    public ReadOnlyTreeSet
249        (Class<E> elementsType, Comparator<? super E> comparator, Object... elements)
250    {
251        Objects.requireNonNull(elementsType, ROHelpers.NULL_MSG + "'elementsType'");
252
253        fromBuilderOrTreeSet = false;
254
255        if (elements.length == 0)
256            this.treeSet = (TreeSet<E>) EMPTY_TREE_SET;
257
258        else 
259        {
260            this.treeSet = (comparator != null)
261                ? new TreeSet<>(comparator)
262                : new TreeSet<>();
263
264            for (Object element : elements) this.treeSet.add(elementsType.cast(element));
265        }
266    }
267
268    /**
269     * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents
270     * {@code 'elements'}.
271     * 
272     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
273     * 
274     * @param mapper     <EMBED CLASS='external-html' DATA-FILE-ID=OBJ_E_MAPPER>
275     * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
276     * @param elements   <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
277     * 
278     * @throws ClassCastException   <EMBED CLASS='external-html' DATA-FILE-ID=CCEX>
279     * @throws NullPointerException If {@code 'mapper'} is passed null.
280     */
281    public ReadOnlyTreeSet(
282            Function<Object, ? extends E>   mapper,
283            Comparator<? super E>           comparator,
284            Object...                       elements
285        )
286    {
287        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
288
289        fromBuilderOrTreeSet = false;
290
291        if (elements.length == 0)
292            this.treeSet = (TreeSet<E>) EMPTY_TREE_SET;
293
294        else 
295        {
296            this.treeSet = (comparator != null)
297                ? new TreeSet<>(comparator)
298                : new TreeSet<>();
299
300            for (Object element : elements) this.treeSet.add(mapper.apply(element));
301        }
302    }
303
304
305    // ********************************************************************************************
306    // ********************************************************************************************
307    // Iterable & Array Based Constructors - **INCLUDES ELEMENT FILTER**
308    // ********************************************************************************************
309    // ********************************************************************************************
310
311
312    /**
313     * If only a small amount of processing needs to be done on the contents of some Java
314     * Data-Type, and using an entire Builder-Class seems disproportionately complex - <I>this
315     * constructor can convert any Java {@code Iterable} into a {@code ReadOnlyTreeSet}, using
316     * a simple {@code 'mapper'}</I>.
317     * 
318     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
319     * 
320     * @param <T>        <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_TYPE_PARAM>
321     * @param i          Any Java {@code Iterable<T>}
322     * @param mapper     <EMBED CLASS='external-html' DATA-FILE-ID=ITERABLE_MAPPER>
323     * @param filter     <EMBED CLASS='external-html' DATA-FTP=T DATA-FILE-ID=PREDICATE_FILTER>
324     * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
325     * 
326     * @throws NullPointerException if any of {@code 'i'}, {@code 'mapper'} or {@code 'filter'} are
327     * passed null
328     */
329    public <T> ReadOnlyTreeSet(
330            Iterable<T>                         i,
331            Function<? super T, ? extends E>    mapper,
332            Predicate<? super T>                filter,
333            Comparator<? super E>               comparator
334        )
335    {
336        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
337        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
338
339        fromBuilderOrTreeSet = false;
340
341        TreeSet<E> treeSet = (comparator != null)
342            ? new TreeSet<>(comparator)
343            : new TreeSet<>();
344
345        for (T t : i) if (filter.test(t)) treeSet.add(mapper.apply(t));
346
347        // Empty Optimization (throw away, completely, the reference, use static-constant)
348        this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet;
349    }
350
351    /**
352     * If a Standard Java {@code Iterable} can be directly mapped into a {@code TreeSet}
353     * (and, ergo, an entire Builder-Instance would be a bit excessive) - <I>this constructor will
354     * seamlessly convert any Java {@code Iterable<E>} directly into a {@code ReadOnlyTreeSet<E>}
355     * with just this single invocation</I>.
356     * 
357     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
358     * 
359     * @param i          Any Java {@code Iterabler<E>}
360     * @param filter     <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER>
361     * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
362     * 
363     * @throws NullPointerException if either {@code 'i'} or {@code 'filter'} are passed null
364     */
365    public ReadOnlyTreeSet
366        (Iterable<E> i, Predicate<? super E> filter, Comparator<? super E> comparator)
367    {
368        fromBuilderOrTreeSet = false;
369
370        TreeSet<E> treeSet = (comparator != null)
371            ? new TreeSet<>(comparator)
372            : new TreeSet<>();
373
374        for (E element : i) if (filter.test(element)) treeSet.add(element);
375
376        // Empty Optimization (throw away, completely, the reference, use static-constant)
377        this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet;
378    }
379
380    /**
381     * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents
382     * {@code 'elements'}.
383     * 
384     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
385     * 
386     * @param elementsType  <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_TYPE>
387     * @param filter        <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER>
388     * @param comparator    <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
389     * @param elements      <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
390     * 
391     * @throws ClassCastException <EMBED CLASS='external-html' DATA-FILE-ID=CCEX>
392     * 
393     * @throws NullPointerException If either {@code 'elementsType'} or {@code 'filter'} are passed
394     * null.
395     */
396    public ReadOnlyTreeSet(
397            Class<E>                elementsType,
398            Predicate<? super E>    filter,
399            Comparator<? super E>   comparator,
400            Object...               elements
401        )
402    {
403        Objects.requireNonNull(elementsType, ROHelpers.NULL_MSG + "'elementsType'");
404        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
405
406        fromBuilderOrTreeSet = false;
407
408        TreeSet<E> treeSet = (comparator != null)
409            ? new TreeSet<>(comparator)
410            : new TreeSet<>();
411
412        E e;
413        for (Object element : elements)
414            if (filter.test(e = elementsType.cast(element)))
415                treeSet.add(e);
416
417        // Empty Optimization (throw away, completely, the reference, use static-constant)
418        this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet;
419    }
420
421    /**
422     * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents
423     * {@code 'elements'}.
424     * 
425     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
426     * 
427     * @param mapper     <EMBED CLASS='external-html' DATA-FILE-ID=OBJ_E_MAPPER>
428     * @param filter     <EMBED CLASS='external-html' DATA-FTP=Object DATA-FILE-ID=PREDICATE_FILTER>
429     * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
430     * @param elements   <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
431     * 
432     * @throws ClassCastException   <EMBED CLASS='external-html' DATA-FILE-ID=CCEX>
433     * @throws NullPointerException If either {@code 'mapper'} or {@code 'filter'} are passed null
434     */
435    public ReadOnlyTreeSet(
436            Function<Object, ? extends E>   mapper,
437            Predicate<Object>               filter,
438            Comparator<? super E>           comparator,
439            Object...                       elements
440        )
441    {
442        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
443        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
444
445        fromBuilderOrTreeSet = false;
446
447        TreeSet<E> treeSet = (comparator != null)
448            ? new TreeSet<>(comparator)
449            : new TreeSet<>();
450
451        for (Object element : elements)
452            if (filter.test(element))
453                treeSet.add(mapper.apply(element));
454
455        // Empty Optimization (throw away, completely, the reference, use static-constant)
456        this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet;
457    }
458
459
460    // ********************************************************************************************
461    // ********************************************************************************************
462    // @SafeVarargs / Variable-Arity / VarArgs: with Parameterized / Generic Type's
463    // ********************************************************************************************
464    // ********************************************************************************************
465
466
467    /**
468     * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents
469     * {@code 'elements'}.
470     * 
471     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
472     *
473     * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
474     * @param elements   <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
475     */
476    @SafeVarargs
477    public ReadOnlyTreeSet(Comparator<? super E> comparator, E... elements)
478    {
479        fromBuilderOrTreeSet = false;
480
481        if (elements.length == 0)
482            this.treeSet = (TreeSet<E>) EMPTY_TREE_SET;
483
484        else 
485        {
486            this.treeSet = (comparator != null)
487                ? new TreeSet<>(comparator)
488                : new TreeSet<>();
489
490            for (E e : elements) this.treeSet.add(e);
491        }
492    }
493
494    /**
495     * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents
496     * {@code 'elements'}.
497     * 
498     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
499     * 
500     * @param <T>        <EMBED CLASS='external-html' DATA-FILE-ID=VARARGS_TYPE_PARAM>
501     * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
502     * @param mapper     <EMBED CLASS='external-html' DATA-FILE-ID=T_ARR_E_MAPPER>
503     * @param elements   <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
504     * 
505     * @throws NullPointerException If {@code 'mapper'} is passed null.
506     */
507    @SafeVarargs
508    public <T> ReadOnlyTreeSet(
509            Comparator<? super E>               comparator,
510            Function<? super T, ? extends E>    mapper,
511            T...                                elements
512        )
513    {
514        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
515
516        fromBuilderOrTreeSet = false;
517
518        if (elements.length == 0)
519            this.treeSet = (TreeSet<E>) EMPTY_TREE_SET;
520
521        else 
522        {
523            this.treeSet = (comparator != null)
524                ? new TreeSet<>(comparator)
525                : new TreeSet<>();
526
527            for (T t : elements) this.treeSet.add(mapper.apply(t));
528        }
529    }
530
531    /**
532     * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents
533     * {@code 'elements'}.
534     * 
535     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
536     * 
537     * @param filter     <EMBED CLASS='external-html' DATA-FTP=E DATA-FILE-ID=PREDICATE_FILTER>
538     * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
539     * @param elements   <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
540     * 
541     * @throws NullPointerException If {@code 'filter'} is passed null.
542     */
543    @SafeVarargs
544    public ReadOnlyTreeSet(
545            Predicate<? super E>    filter,
546            Comparator<? super E>   comparator,
547            E...                    elements
548        )
549    {
550        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
551
552        fromBuilderOrTreeSet = false;
553
554        TreeSet<E> treeSet = (comparator != null)
555            ? new TreeSet<>(comparator)
556            : new TreeSet<>();
557
558        for (E e : elements) if (filter.test(e)) treeSet.add(e);
559
560        // Empty Optimization (throw away, completely, the reference, use static-constant)
561        this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet;
562    }
563
564    /**
565     * Builds {@code ReadOnlyTreeSet<E>} instance having Generic-Type {@code 'E'}, and contents
566     * {@code 'elements'}.
567     * 
568     * <EMBED CLASS='external-html' DATA-FILE-ID=TREESET_CMPR_WARN>
569     * 
570     * @param <T>           <EMBED CLASS='external-html' DATA-FILE-ID=VARARGS_TYPE_PARAM>
571     * @param filter        <EMBED CLASS='external-html' DATA-FTP=T DATA-FILE-ID=PREDICATE_FILTER>
572     * @param mapper        <EMBED CLASS='external-html' DATA-FILE-ID=T_ARR_E_MAPPER>
573     * @param comparator    <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
574     * @param elements      <EMBED CLASS='external-html' DATA-FILE-ID=ELEMENTS_VAR_ARGS>
575     * 
576     * @throws NullPointerException If either {@code 'mapper'} or {@code 'filter'} are passed null
577     */
578    @SafeVarargs
579    public <T> ReadOnlyTreeSet(
580            Predicate<? super T>                filter,
581            Function<? super T, ? extends E>    mapper,
582            Comparator<? super E>               comparator,
583            T...                                elements
584        )
585    {
586        Objects.requireNonNull(mapper, ROHelpers.NULL_MSG + "'mapper'");
587        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
588
589        fromBuilderOrTreeSet = false;
590
591        TreeSet<E> treeSet = (comparator != null)
592            ? new TreeSet<>(comparator)
593            : new TreeSet<>();
594
595        for (T t : elements) if (filter.test(t)) treeSet.add(mapper.apply(t));
596
597        // Empty Optimization (throw away, completely, the reference, use static-constant)
598        this.treeSet = (treeSet.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : treeSet;
599    }
600
601
602    // ********************************************************************************************
603    // ********************************************************************************************
604    // PRIMITIVE-ARRAY INPUT
605    // ********************************************************************************************
606    // ********************************************************************************************
607
608
609    /**
610     * Converts a Java Primitive-Array to a {@code ReadOnlyTreeSet<E>}, where {@code 'E'} is the
611     * Java Boxed-Type which corresponds to the Primitive-Array's Type.
612     *
613     * <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CTOR_DESC>
614     * @param primitiveArray        <EMBED CLASS='external-html' DATA-FILE-ID=PRIMITIVE_ARRAY>
615     * @throws ClassCastException   <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CCEX>
616     * @throws NullPointerException If {@code 'primitiveArray'} is passed null;
617     */
618    public ReadOnlyTreeSet(Object primitiveArray, Comparator<? super E> comparator)
619    {
620        fromBuilderOrTreeSet = false;
621
622        TreeSet<E> ts = ROHelpers.buildROListOrSet(
623            primitiveArray,
624            (int arrayLen) -> (comparator != null) ? new TreeSet<E>(comparator) : new TreeSet<E>(),
625            null
626        );
627
628        // Empty Optimization (throw away, completely, the reference, use static-constant)
629        this.treeSet = (ts.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : ts;
630    }
631
632    /**
633     * Converts a Java Primitive-Array to a {@code ReadOnlyTreeSet<E>}, where {@code 'E'} is the
634     * Java Boxed-Type which corresponds to the Primitive-Array's Type - <I>but also accepts a 
635     * {@code 'filter'} that can remove any array-entries that need to be removed</I>.
636     *
637     * <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CTOR_DESC>
638     * @param primitiveArray        <EMBED CLASS='external-html' DATA-FILE-ID=PRIMITIVE_ARRAY>
639     * @param filter                <EMBED CLASS='external-html' DATA-FILE-ID=PRED_FILT_PRIM>
640     * @throws ClassCastException   <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CCEX>
641     * @throws NullPointerException If {@code 'primitiveArray'} is passed null;
642     */
643    public ReadOnlyTreeSet(
644            Object                  primitiveArray,
645            Comparator<? super E>   comparator,
646            Predicate<?>            filter
647        )
648    {
649        Objects.requireNonNull(filter, ROHelpers.NULL_MSG + "'filter'");
650
651        fromBuilderOrTreeSet = false;
652
653        TreeSet<E> ts = ROHelpers.buildROListOrSet(
654            primitiveArray,
655            (int arrayLen) -> (comparator != null) ? new TreeSet<E>(comparator) : new TreeSet<E>(),
656            filter
657        );
658
659        // Empty Optimization (throw away, completely, the reference, use static-constant)
660        this.treeSet = (ts.size() == 0) ? ((TreeSet<E>) EMPTY_TREE_SET) : ts;
661    }
662
663
664    // ********************************************************************************************
665    // ********************************************************************************************
666    // java.util.stream.Stream HELPER
667    // ********************************************************************************************
668    // ********************************************************************************************
669
670
671    /**
672     * For use with a the Java Stream method {@code 'collect(Collector c)'}.
673     * 
674     * <EMBED CLASS='external-html' DATA-ABBREV=ts DATA-FILE-ID=STREAM_COLLECTOR>
675     * 
676     * @param <T> This is the Generic-Type of the Input-Stream.  It will also be the Generic-Type
677     * of the {@code ReadOnlyTreeSet} that's returned from the stream's {@code collect} method.
678     * 
679     * @param characteristics Optional Characteristics List.  See Java Stream-API Documentation on
680     * {@code Collector.Characteristics} inner-class for more details.
681     * 
682     * @return This returns a collector that may be piped into a stream's {@code 'collect'} method,
683     * as in the example, above.
684     */
685    public static <T> java.util.stream.Collector
686        <T, ROTreeSetBuilder<T>, ReadOnlyTreeSet<T>>
687        streamCollector(Collector.Characteristics... characteristics)
688    {
689        return Collector.of(
690            ROTreeSetBuilder<T>::new,    // The "Supplier"    (builds a new ROTreeSetBuilder)
691            ROTreeSetBuilder<T>::add,    // The "Accumulator" (adds elements to the builder)
692
693            // Oracle Making Life Difficult - It should be the line below, but, alas, it is not!
694            // ROTreeSetBuilder<T>::addAll, // The "Combiner"    (combines multiple ROTreeSetBuilders)
695            //
696            // In Stream.collect(), the 3rd parameter - the "combiner" - is a "BiConsumer<R, R>"
697            // NOTE: A "BiConsumer" is a FunctionalInterface that does not return anything - it is
698            // (obviously) a "void" return method!
699            //
700            // **BUT**
701            //
702            // In Collector.of, the 3rd parameter - the "combiner" - is a "BinaryOperation<R>"
703    
704            (ROTreeSetBuilder<T> rotsb1, ROTreeSetBuilder<T> rotsb2) ->
705            {
706                rotsb1.addAll(rotsb2);
707                return rotsb1;
708            },
709
710            ROTreeSetBuilder<T>::build,  // The "Finisher"    (Converts Builder to ReadOnlyTreeSet)
711            characteristics
712        );
713    }
714
715
716    // ********************************************************************************************
717    // ********************************************************************************************
718    // Convert to java.util Types
719    // ********************************************************************************************
720    // ********************************************************************************************
721
722
723    /**
724     * Clone's {@code 'this'} instance internal {@code TreeSet<E>} field, and returns it. 
725     * <EMBED CLASS='external-html' DATA-TYPE=TreeSet DATA-FILE-ID=CLONE_TO>
726     * 
727     * @return An independent, mutable copy of {@code 'this'} instance' internal {@code TreeSet<E>}
728     * data-structure.
729     */
730    public TreeSet<E> cloneToTreeSet()
731    {
732        return fromBuilderOrTreeSet
733            ? new TreeSet<E>(this.treeSet)
734            : (TreeSet<E>) this.treeSet.clone(); 
735    }
736
737    /**
738     * Invokes {@code java.util.Collections.unmodifiableSet} on the internal {@code TreeSet}.
739     * <EMBED CLASS='external-html' DATA-RET_TYPE=Set DATA-FILE-ID=WRAP_TO_IMMUTABLE>
740     * 
741     * @return A {@code Set} which adheres to the JDK interface {@code java.util.Set}, but throws
742     * an {@code UnsupportedOperationException} if a user attempts to invoke a Mutator-Method on
743     * the returned instance.
744     */
745    public Set<E> wrapToImmutableSet()
746    { return Collections.unmodifiableSet(this.treeSet); }
747
748
749    // ********************************************************************************************
750    // ********************************************************************************************
751    // Original JDK Methods, java.util.TreeSet
752    // ********************************************************************************************
753    // ********************************************************************************************
754
755
756    /**
757     * Returns an iterator over the elements in this set in ascending order.
758     * @return an iterator over the elements in this set in ascending order
759     */
760    public RemoveUnsupportedIterator<E> iterator()
761    { return new RemoveUnsupportedIterator<>(this.treeSet.iterator()); }
762 
763    /**
764     * Returns an iterator over the elements in this set in descending order.
765     * @return an iterator over the elements in this set in descending order
766     */
767    public RemoveUnsupportedIterator<E> descendingIterator()
768    { return new RemoveUnsupportedIterator<>(this.treeSet.descendingIterator()); }
769
770    public ReadOnlyNavigableSet<E> descendingSet()
771    {
772        return InterfaceBuilder.toReadOnlyNavigableSet(
773            fromBuilderOrTreeSet
774                ? ((ROTreeSetBuilder<E>) this.treeSet)._descendingSet(friendClassBadge)
775                : this.treeSet.descendingSet()
776        );
777    }
778 
779    /**
780     * Returns the number of elements in this set (its cardinality).
781     * @return the number of elements in this set (its cardinality)
782     */
783    public int size()
784    { return this.treeSet.size(); }
785 
786    /**
787     * Returns {@code TRUE} if this set contains no elements.
788     * @return {@code TRUE} if this set contains no elements
789     */
790    public boolean isEmpty()
791    { return this.treeSet.isEmpty(); }
792 
793    /**
794     * Returns {@code TRUE} if this set contains the specified element.  More formally, returns
795     * {@code TRUE} if and only if this set contains an element {@code e} such that
796     * {@code Objects.equals(o, e)}.
797     *
798     * @param o object to be checked for containment in this set
799     * @return {@code TRUE} if this set contains the specified element
800     * 
801     * @throws ClassCastException if the specified object cannot be compared with the elements
802     * currently in the set
803     * 
804     * @throws NullPointerException if the specified element is null and this set uses natural
805     * ordering, or its comparator does not permit null elements
806     */
807    public boolean contains(Object o)
808    { return this.treeSet.contains(o); }
809  
810    /**
811     * @throws ClassCastException {@inheritDoc}
812     * 
813     * @throws NullPointerException if {@code fromElement} or {@code toElement} is null and this
814     * set uses natural ordering, or its comparator does not permit null elements
815     * 
816     * @throws IllegalArgumentException {@inheritDoc}
817     */
818    public ReadOnlyNavigableSet<E> subSet(
819            E fromElement, boolean fromInclusive,
820            E toElement,   boolean toInclusive
821        )
822    {
823        return InterfaceBuilder.toReadOnlyNavigableSet(
824            fromBuilderOrTreeSet
825                ? ((ROTreeSetBuilder<E>) this.treeSet)._subSet
826                    (fromElement, fromInclusive, toElement, toInclusive, friendClassBadge)
827                : this.treeSet.subSet(fromElement, fromInclusive, toElement, toInclusive)
828        );
829    }
830 
831    /**
832     * @throws ClassCastException {@inheritDoc}
833     * 
834     * @throws NullPointerException if {@code toElement} is null and this set uses natural
835     * ordering, or its comparator does not permit null elements
836     * 
837     * @throws IllegalArgumentException {@inheritDoc}
838     */
839    public ReadOnlyNavigableSet<E> headSet(E toElement, boolean inclusive)
840    {
841        return InterfaceBuilder.toReadOnlyNavigableSet(
842            fromBuilderOrTreeSet
843                ? ((ROTreeSetBuilder<E>) this.treeSet)._headSet
844                    (toElement, inclusive, friendClassBadge)
845                : this.treeSet.headSet(toElement, inclusive)
846        );
847    }
848 
849    /**
850     * @throws ClassCastException {@inheritDoc}
851     * 
852     * @throws NullPointerException if {@code fromElement} is null and this set uses natural
853     * ordering, or its comparator does not permit null elements
854     * 
855     * @throws IllegalArgumentException {@inheritDoc}
856     */
857    public ReadOnlyNavigableSet<E> tailSet(E fromElement, boolean inclusive)
858    {
859        return InterfaceBuilder.toReadOnlyNavigableSet(
860            fromBuilderOrTreeSet
861                ? ((ROTreeSetBuilder<E>) this.treeSet)._tailSet
862                    (fromElement, inclusive, friendClassBadge)
863                : this.treeSet.tailSet(fromElement, inclusive)
864        );
865    }
866 
867    /**
868     * @throws ClassCastException {@inheritDoc}
869     * 
870     * @throws NullPointerException if {@code fromElement} or {@code toElement} is null and this
871     * set uses natural ordering, or its comparator does not permit null elements
872     * 
873     * @throws IllegalArgumentException {@inheritDoc}
874     */
875    public ReadOnlySortedSet<E> subSet(E fromElement, E toElement)
876    {
877        return InterfaceBuilder.toReadOnlySortedSet(
878            fromBuilderOrTreeSet
879                ? ((ROTreeSetBuilder<E>) this.treeSet)._subSet
880                    (fromElement, toElement, friendClassBadge)
881                : this.treeSet.subSet(fromElement, toElement)
882        );
883    }
884
885    /**
886     * @throws ClassCastException {@inheritDoc}
887     * 
888     * @throws NullPointerException if {@code toElement} is null and this set uses natural
889     * ordering, or its comparator does not permit null elements
890     * 
891     * @throws IllegalArgumentException {@inheritDoc}
892     */
893    public ReadOnlySortedSet<E> headSet(E toElement)
894    {
895        return InterfaceBuilder.toReadOnlySortedSet(
896            fromBuilderOrTreeSet
897                ? ((ROTreeSetBuilder<E>) this.treeSet)._headSet(toElement, friendClassBadge)
898                : this.treeSet.headSet(toElement)
899        );
900    }
901
902    /**
903     * @throws ClassCastException {@inheritDoc}
904     * 
905     * @throws NullPointerException if {@code fromElement} is null and this set uses natural
906     * ordering, or its comparator does not permit null elements
907     * 
908     * @throws IllegalArgumentException {@inheritDoc}
909     */
910    public ReadOnlySortedSet<E> tailSet(E fromElement)
911    {
912        return InterfaceBuilder.toReadOnlySortedSet(
913            fromBuilderOrTreeSet
914                ? ((ROTreeSetBuilder<E>) this.treeSet)._tailSet(fromElement, friendClassBadge)
915                : this.treeSet.tailSet(fromElement)
916        );
917    }
918 
919    public Comparator<? super E> comparator()
920    { return this.treeSet.comparator(); }
921 
922    /** @throws NoSuchElementException {@inheritDoc} */
923    public E first()
924    { return this.treeSet.first(); }
925 
926    /** @throws NoSuchElementException {@inheritDoc} */
927    public E last()
928    { return this.treeSet.last(); }
929
930    /**
931     * @throws ClassCastException {@inheritDoc}
932     * 
933     * @throws NullPointerException if the specified element is null and this set uses natural
934     * ordering, or its comparator does not permit null elements
935     */
936    public E lower(E e)
937    { return this.treeSet.lower(e); }
938
939    /**
940     * @throws ClassCastException {@inheritDoc}
941     * 
942     * @throws NullPointerException if the specified element is null and this set uses natural
943     * ordering, or its comparator does not permit null elements
944     */
945    public E floor(E e)
946    { return this.treeSet.floor(e); }
947
948    /**
949     * @throws ClassCastException {@inheritDoc}
950     * 
951     * @throws NullPointerException if the specified element is null and this set uses natural
952     * ordering, or its comparator does not permit null elements
953     */
954    public E ceiling(E e)
955    { return this.treeSet.ceiling(e); }
956
957    /**
958     * @throws ClassCastException {@inheritDoc}
959     * 
960     * @throws NullPointerException if the specified element is null and this set uses natural
961     * ordering, or its comparator does not permit null elements
962     */
963    public E higher(E e)
964    { return this.treeSet.higher(e); }
965
966    /**
967     * Utilizes the private, internal {@code java.util.TreeSet} field to generate a
968     * {@code Spliterator}.
969     * 
970     * @return a {@code Spliterator} over the elements in this set
971     */
972    public Spliterator<E> spliterator()
973    { return this.treeSet.spliterator(); }
974
975
976    // ********************************************************************************************
977    // ********************************************************************************************
978    // Misc Stuff that is defined in a super-class - for java.util, but not for Java.ReadOnly
979    // ********************************************************************************************
980    // ********************************************************************************************
981
982
983    public boolean containsAll(Collection<?> c)
984    { return this.treeSet.containsAll(c); }
985
986    public <T> T[] toArray​(T[] a)
987    { return this.treeSet.toArray(a); }
988
989    public Object[] toArray()
990    { return this.treeSet.toArray(); }
991
992
993    // ********************************************************************************************
994    // ********************************************************************************************
995    // java.lang.Object
996    // ********************************************************************************************
997    // ********************************************************************************************
998
999
1000    /**
1001     * Returns a {@code String} representation of this {@code TreeSet}. The {@code String}
1002     * representation consists of a list of the collection's elements in the order they are
1003     * returned by its iterator, enclosed in square brackets ({@code "[]"}). Adjacent elements are
1004     * separated by the characters {@code ", "} (comma and space). Elements are converted to
1005     * {@code String's} as by {@code String.valueOf(Object)}.
1006     * 
1007     * @return a {@code String} representation of this {@code TreeSet}
1008     */
1009    public String toString()
1010    { return this.treeSet.toString(); }
1011
1012    /**
1013     * Compares the specified Object with this Set for equality, as per the definition in the 
1014     * class {@code java.util.TreeSet}.
1015     *
1016     * @param  o object to be compared for equality with this {@code ReadOnlyTreeSet}.
1017     * @return {@code TRUE} if the specified Object is equal to this set
1018     */
1019    public boolean equals(Object o)
1020    { return ROHelpers.roSetEq(this, o); }
1021
1022    /**
1023     * Returns the hash code value for this Set as per the definition in the class
1024     * {@code java.util.TreeSet}.
1025     */
1026    public int hashCode() 
1027    { return this.treeSet.hashCode(); }
1028}
1029