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 java.io.Serializable;
028import java.util.function.Predicate;
029
030import java.util.*;
031
032import Torello.Java.Additional.RemoveUnsupportedIterator;
033
034
035/**
036 * A Copy of Java's {@code TreeSet} class; used for building a {@link ReadOnlyTreeSet}.  Maintains
037 * <I>an internal and inaccessible {@code TreeSet<E>} instance</I>.  
038 * 
039 * <EMBED CLASS=globalDefs DATA-JDK=Vector>
040 * <EMBED CLASS='external-html' DATA-A_AN=a DATA-FILE-ID=BUILDERS>
041 * 
042 * @param <E> the type of elements maintained by this set
043 * @see ReadOnlyTreeSet
044 */
045@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="JDHBI_BUILDER")
046public final class ROTreeSetBuilder<E>
047    extends TreeSet<E>
048    implements Cloneable, Serializable
049{
050    // ********************************************************************************************
051    // ********************************************************************************************
052    // Fields & Builder
053    // ********************************************************************************************
054    // ********************************************************************************************
055
056
057    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
058    protected static final long serialVersionUID = 1;
059
060    // Exception messages need this
061    private static final String ROTS = "TreeSet";
062
063    private boolean built = false;
064
065    // Mimics the C++ Concept of "Friend Class".  This badge is utilized by the "build()" method
066    // directly below this inner-class declaration.  It is the only place where this declaration is
067    // actually used anywhere.  This prohibits access to the constructor that is used to anybody
068    // else
069
070    static class AccessBadge { private AccessBadge() { } }
071    private static final AccessBadge friendClassBadge = new AccessBadge();
072
073    /**
074     * Simply transfers {@code 'this'} instance' internal {@code TreeSet} to the 
075     * {@code ReadOnlyTreeSet} Wrapper-Class.
076     * 
077     * @return a newly constructed {@code ReadOnlyTreeSet} "Wrapper-Class", shielding the
078     * internal {@code 'treeSet'} private-field from any modification.
079     */
080    public ReadOnlyTreeSet<E> build()
081    {
082        this.built = true;
083
084        return (size() == 0)
085            ? ReadOnlyTreeSet.emptyROTS()
086            : new ReadOnlyTreeSet<E>(this, friendClassBadge);
087    }
088
089
090    // ********************************************************************************************
091    // ********************************************************************************************
092    // Modified Constructors
093    // ********************************************************************************************
094    // ********************************************************************************************
095
096
097    /**
098     * Constructs a new, empty tree set, sorted according to the natural ordering of its elements.
099     * All elements inserted into the set must implement the {@code Comparable} interface.
100     * Furthermore, all such elements must be <i>mutually comparable</i>: {@code e1.compareTo(e2)}
101     * must not throw a {@code ClassCastException} for any elements {@code e1} and {@code e2} in
102     * the set.  If the user attempts to add an element to the set that violates this constraint
103     * (for example, the user attempts to add a string element to a set whose elements are
104     * integers), the {@code add} call will throw a {@code ClassCastException}.
105     */
106    public ROTreeSetBuilder()
107    { super(); }
108
109    /**
110     * Constructs a new, empty tree set, sorted according to the specified comparator.  All
111     * elements inserted into the set must be <i>mutually comparable</i> by the specified
112     * comparator: {@code comparator.compare(e1, e2)} must not throw a {@code ClassCastException}
113     * for any elements {@code e1} and {@code e2} in the set.  If the user attempts to add an
114     * element to the set that violates this constraint, the {@code add} call will throw a
115     * {@code ClassCastException}.
116     *
117     * @param comparator the comparator that will be used to order this set.  If {@code null}, the
118     * {@linkplain Comparable natural ordering} of the elements will be used.
119     */
120    public ROTreeSetBuilder(Comparator<? super E> comparator)
121    { super(comparator); }
122
123    /**
124     * Constructs a new tree set containing the elements in the specified collection, sorted
125     * according to the <i>natural ordering</i> of its elements.  All elements inserted into the
126     * set must implement the {@link Comparable} interface.  Furthermore, all such elements must be
127     * <i>mutually comparable</i>: {@code e1.compareTo(e2)} must not throw a
128     * {@code ClassCastException} for any elements {@code e1} and {@code e2} in the set.
129     *
130     * @param c collection whose elements will comprise the new set
131     * 
132     * @throws ClassCastException if the elements in {@code c} are not {@link Comparable}, or are
133     * not mutually comparable
134     * 
135     * @throws NullPointerException if the specified collection is null
136     */
137    public ROTreeSetBuilder(Collection<? extends E> c)
138    { super(c); }
139
140    /**
141     * Constructs a new tree set containing the same elements and using the same ordering as the
142     * specified sorted set.
143     *
144     * @param s sorted set whose elements will comprise the new set
145     * @throws NullPointerException if the specified sorted set is null
146     */
147    public ROTreeSetBuilder(SortedSet<E> s)
148    { super(s); }
149
150
151    // ********************************************************************************************
152    // ********************************************************************************************
153    // Original JDK Methods
154    // ********************************************************************************************
155    // ********************************************************************************************
156
157
158    /**
159     * Restricts a back-door into the underlying data-structure.
160     * <EMBED CLASS='external-html'DATA-RET_TYPE=xx DATA-FILE-ID=UNMODIFIABLE>
161     * @return a {@code java.util.Iterator} that cannot modify this {@code Vector-Builder}
162     */
163    public RemoveUnsupportedIterator<E> iterator()
164    { return new RemoveUnsupportedIterator<>(super.iterator()); }
165
166    /**
167     * Restricts a back-door into the underlying data-structure.
168     * <EMBED CLASS='external-html'DATA-RET_TYPE=xx DATA-FILE-ID=UNMODIFIABLE>
169     * @return a {@code java.util.Iterator} that cannot modify this {@code Vector-Builder}
170     */
171    public RemoveUnsupportedIterator<E> descendingIterator()
172    { return new RemoveUnsupportedIterator<>(super.descendingIterator()); }
173
174    /**
175     * Adds the specified element to this set if it is not already present.  More formally, adds
176     * the specified element {@code e} to this set if the set contains no element {@code e2} such
177     * that {@code Objects.equals(e, e2)}.  If this set already contains the element, the call
178     * leaves the set unchanged and returns {@code FALSE}.
179     * 
180     * <EMBED DATA-TYPE=TreeMap CLASS='external-html' DATA-FILE-ID=MUTATOR>
181     * 
182     * @param e element to be added to this set
183     * @return {@code TRUE} if this set did not already contain the specified element
184     * 
185     * @throws ClassCastException if the specified object cannot be compared with the elements
186     * currently in this set
187     * 
188     * @throws NullPointerException if the specified element is null and this set uses natural
189     * ordering, or its comparator does not permit null elements
190     */
191    public boolean add(E e)
192    {
193        if (this.built) throw new AttemptedModificationException(ROTS);
194        return super.add(e); 
195    }
196
197    /**
198     * Removes the specified element from this set if it is present.  More formally, removes an
199     * element {@code e} such that {@code Objects.equals(o, e)}, if this set contains such an
200     * element.  Returns {@code TRUE} if this set contained the element (or equivalently, if this
201     * set changed as a result of the call).  (This set will not contain the element once the call
202     * returns.)
203     * 
204     * <EMBED DATA-TYPE=TreeMap CLASS='external-html' DATA-FILE-ID=MUTATOR>
205     * 
206     * @param o object to be removed from this set, if present
207     * @return {@code TRUE} if this set contained the specified element
208     * 
209     * @throws ClassCastException if the specified object cannot be compared with the elements
210     * currently in this set
211     * 
212     * @throws NullPointerException if the specified element is null and this set uses natural
213     * ordering, or its comparator does not permit null elements
214     */
215    public boolean remove(Object o)
216    {
217        if (this.built) throw new AttemptedModificationException(ROTS);
218        return super.remove(o); 
219    }
220
221    /**
222     * Removes all of the elements from this set.  The set will be empty after this call returns.
223     * <EMBED DATA-TYPE=TreeMap CLASS='external-html' DATA-FILE-ID=MUTATOR>
224     */
225    public void clear()
226    {
227        if (this.built) throw new AttemptedModificationException(ROTS);
228        super.clear(); 
229    }
230
231    /**
232     * Adds all of the elements in the specified collection to this set.
233     * 
234     * <EMBED DATA-TYPE=TreeMap CLASS='external-html' DATA-FILE-ID=MUTATOR>
235     *
236     * @param c collection containing elements to be added to this set
237     * @return {@code TRUE} if this set changed as a result of the call
238     * 
239     * @throws ClassCastException if the elements provided cannot be compared with the elements
240     * currently in the set
241     * 
242     * @throws NullPointerException if the specified collection is null or if any element is null
243     * and this set uses natural ordering, or its comparator does not permit null elements
244     */
245    public  boolean addAll(Collection<? extends E> c)
246    {
247        if (this.built) throw new AttemptedModificationException(ROTS);
248        return super.addAll(c); 
249    }
250
251    /**
252     * Retrieves and removes the first (lowest) element, or returns null if this set is empty.
253     * <EMBED DATA-TYPE=TreeMap CLASS='external-html' DATA-FILE-ID=MUTATOR>
254     * @return the first element, or null if this set is empty
255     */
256    public E pollFirst()
257    {
258        if (this.built) throw new AttemptedModificationException(ROTS);
259        return super.pollFirst(); 
260    }
261
262    /**
263     * Retrieves and removes the last (highest) element, or returns null if this set is empty.
264     * <EMBED DATA-TYPE=TreeMap CLASS='external-html' DATA-FILE-ID=MUTATOR>
265     * @return the last element, or null if this set is empty
266     */
267    public E pollLast()
268    {
269        if (this.built) throw new AttemptedModificationException(ROTS);
270        return super.pollLast(); 
271    }
272
273
274    // ********************************************************************************************
275    // ********************************************************************************************
276    // Methods inherited from class java.util.TreeSet
277    // ********************************************************************************************
278    // ********************************************************************************************
279
280
281    // ceiling, comparator, contains, descendingIterator, descendingSet, first, floor, headSet,
282    // headSet, higher, isEmpty, iterator, last, lower, size, spliterator, subSet, subSet, tailSet,
283    // tailSet
284    // 
285    // Introspection Only: ceiling, comparator, contains, first, floor, isEmpty, higher, isEmpty,
286    //                     last, lower, size, spliterator, 
287    //
288    // Mutator or Possible Mutator: descendingIterator, descendingSet, headSet, headSet, iterator,
289    //                              subSet, subSet, tailSet, tailSet
290    //
291    // Methods inherited from class java.util.AbstractSet:
292    // hashCode, removeAll
293    // 
294    // Methods inherited from class java.util.AbstractCollection:
295    // containsAll, retainAll, toArray, toArray, toString
296    // 
297    // Methods inherited from interface java.util.Collection:
298    // parallelStream, removeIf, stream, toArray
299    // 
300    // Methods inherited from interface java.lang.Iterable:
301    // forEach
302    //
303    // Methods inherited from interface java.util.Set
304    // containsAll, hashCode, removeAll, retainAll, toArray, toArray
305
306    /**
307     * Restricts a back-door into the underlying data-structure.
308     * <EMBED CLASS='external-html'DATA-RET_TYPE=NavigableSet DATA-FILE-ID=UNMODIFIABLE>
309     * @return a {@code java.util.NavigableSet} that cannot modify this {@code TreeSet-Builder}
310     */
311    public NavigableSet<E> descendingSet()
312    { return Collections.unmodifiableNavigableSet(super.descendingSet()); }
313
314    NavigableSet<E> _descendingSet(ReadOnlyTreeSet.AccessBadge friendClassBadge)
315    { return super.descendingSet(); }
316
317    /**
318     * Restricts a back-door into the underlying data-structure.
319     * <EMBED CLASS='external-html'DATA-RET_TYPE=SortedSet DATA-FILE-ID=UNMODIFIABLE>
320     * @return a {@code java.util.SortedSet} that cannot modify this {@code TreeSet-Builder}
321     */
322    public SortedSet<E> headSet(E toElement)
323    { return Collections.unmodifiableSortedSet(super.headSet(toElement, false)); }
324
325    // *** Java-HTML: 
326    // Looking at the JDK-21 Code for TreeMap, headSet(E toElem) just calls headSet(E, boolean)
327    // This supbstitution has to happen, or else the AccessDeniedException throws
328
329    SortedSet<E> _headSet(E toElement, ReadOnlyTreeSet.AccessBadge friendClassBadge)
330    { return super.headSet(toElement, false); /* Java-HTML: was headSet(toElement) */ }
331
332    /**
333     * Restricts a back-door into the underlying data-structure.
334     * <EMBED CLASS='external-html'DATA-RET_TYPE=NavigableSet DATA-FILE-ID=UNMODIFIABLE>
335     * @return a {@code java.util.NavigableSet} that cannot modify this {@code TreeSet-Builder}
336     */
337    public NavigableSet<E> headSet(E toElement, boolean inclusive)
338    { return Collections.unmodifiableNavigableSet(super.headSet(toElement, inclusive)); }
339
340    NavigableSet<E> _headSet
341        (E toElement, boolean inclusive, ReadOnlyTreeSet.AccessBadge friendClassBadge)
342    { return super.headSet(toElement, inclusive); }
343
344    /**
345     * Restricts a back-door into the underlying data-structure.
346     * <EMBED CLASS='external-html'DATA-RET_TYPE=NavigableSet DATA-FILE-ID=UNMODIFIABLE>
347     * @return a {@code java.util.NavigableSet} that cannot modify this {@code TreeSet-Builder}
348     */
349    public NavigableSet<E> subSet
350        (E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)
351    {
352        return Collections.unmodifiableNavigableSet
353            (super.subSet(fromElement, fromInclusive, toElement, toInclusive));
354    }
355
356    NavigableSet<E> _subSet(
357            E fromElement, boolean fromInclusive, E toElement, boolean toInclusive,
358            ReadOnlyTreeSet.AccessBadge friendClassBadge
359        )
360    { return super.subSet(fromElement, fromInclusive, toElement, toInclusive); }
361
362    /**
363     * Restricts a back-door into the underlying data-structure.
364     * <EMBED CLASS='external-html'DATA-RET_TYPE=SortedSet DATA-FILE-ID=UNMODIFIABLE>
365     * @return a {@code java.util.SortedSet} that cannot modify this {@code TreeSet-Builder}
366     */
367    public SortedSet<E> subSet(E fromElement, E toElement)
368    {
369        return Collections.unmodifiableSortedSet
370            (super.subSet(fromElement, true, toElement, false));
371    }
372
373    // *** Java-HTML: 
374    // Looking at the JDK-21 Code for TreeMap, subSet(E fromElement, E toElem) just calls
375    //      subSet(E, boolean, E, boolean)
376    // This supbstitution has to happen, or else the AccessDeniedException throws
377
378    SortedSet<E> _subSet(E fromElement, E toElement, ReadOnlyTreeSet.AccessBadge friendClassBadge)
379    { return super.subSet(fromElement, true /* added */, toElement, false /* added */); }
380
381    /**
382     * Restricts a back-door into the underlying data-structure.
383     * <EMBED CLASS='external-html'DATA-RET_TYPE=NavigableSet DATA-FILE-ID=UNMODIFIABLE>
384     * @return a {@code java.util.NavigableSet} that cannot modify this {@code TreeSet-Builder}
385     */
386    public NavigableSet<E> tailSet(E fromElement, boolean inclusive)
387    { return Collections.unmodifiableNavigableSet(super.tailSet(fromElement, inclusive)); }
388
389    NavigableSet<E> _tailSet
390        (E fromElement, boolean inclusive, ReadOnlyTreeSet.AccessBadge friendClassBadge)
391    { return super.tailSet(fromElement, inclusive); }
392
393    /**
394     * Restricts a back-door into the underlying data-structure.
395     * <EMBED CLASS='external-html'DATA-RET_TYPE=SortedSet DATA-FILE-ID=UNMODIFIABLE>
396     * @return a {@code java.util.SortedSet} that cannot modify this {@code TreeSet-Builder}
397     */
398    public SortedSet<E> tailSet(E fromElement)
399    { return Collections.unmodifiableSortedSet(super.tailSet(fromElement, true)); }
400
401    // *** Java-HTML: 
402    // Looking at the JDK-21 Code for TreeMap, tailSet(E toElem) just calls tailSet(E, boolean)
403    // This supbstitution has to happen, or else the AccessDeniedException throws
404
405    SortedSet<E> _tailSet(E fromElement, ReadOnlyTreeSet.AccessBadge friendClassBadge)
406    { return super.tailSet(fromElement, true); /* Java-HTML: was headSet(toElement) */ }
407
408
409    // ********************************************************************************************
410    // ********************************************************************************************
411    // More Inherited Methods
412    // ********************************************************************************************
413    // ********************************************************************************************
414
415
416    // Copied Directly from the comments listed in the previous section (above)
417    // 
418    // java.util.AbstractSet:           hashCode, removeAll
419    // java.util.AbstractCollection:    containsAll, retainAll, toArray, toArray, toString
420    // java.util.Collection:            parallelStream, removeIf, stream, toArray
421    // java.lang.Iterable:              forEach
422    // java.util.Set:                   containsAll, hashCode, removeAll, retainAll, toArray
423
424    public boolean removeAll(Collection<?> c)
425    {
426        if (this.built) throw new AttemptedModificationException(ROTS);
427        return super.removeAll(c);
428    }
429
430    public boolean retainAll(Collection<?> c)
431    {
432        if (this.built) throw new AttemptedModificationException(ROTS);
433        return super.retainAll(c);
434    }
435
436    public boolean removeIf(Predicate<? super E> filter)
437    {
438        if (this.built) throw new AttemptedModificationException(ROTS);
439        return super.removeIf(filter);
440    }
441
442
443    // ********************************************************************************************
444    // ********************************************************************************************
445    // java.lang.Object & Cloneable
446    // ********************************************************************************************
447    // ********************************************************************************************
448
449
450    /**
451     * Compares the specified Object with this Builder for equality, as per the definition in the
452     * private and internal field {@code 'treeSet'}.
453     *
454     * @param  o object to be compared for equality with this {@code ROTreeSetBuilder} instance
455     * @return true if the specified Object is equal to this Builder
456     */
457    public boolean equals(Object o)
458    {
459        if (this == o) return true;
460        if (! (o instanceof ROTreeSetBuilder)) return false;
461        return super.equals((TreeSet) o);
462    }
463
464    /**
465     * Clones this instance' of {@code ROTreeSetBuilder}.
466     * 
467     * <BR /><BR />The clone that's returned has had it's internal {@code 'built'} boolean-flag set
468     * {@code FALSE}
469     * 
470     * @return a clone of this builder
471     */
472    public synchronized ROTreeSetBuilder<E> clone()
473    { return new ROTreeSetBuilder<>(this); }
474
475    private ROTreeSetBuilder(ROTreeSetBuilder<E> rohsb)
476    { super(rohsb); this.built=false; }
477}
478