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