001/* 002 * Copyright (c) 1997, 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.function.Predicate; 030import java.util.function.UnaryOperator; 031 032import java.util.*; 033 034import java.io.Serializable; 035 036/** 037 * A Copy of Java's {@code ArrayList} class; used for building a {@link ReadOnlyArrayList}. 038 * Maintains <I>an internal and inaccessible {@code ArrayList<E>} instance</I>. 039 * 040 * <EMBED CLASS=globalDefs DATA-JDK=ArrayList> 041 * <EMBED CLASS='external-html' DATA-A_AN=an DATA-FILE-ID=BUILDERS> 042 * 043 * @param <E> the type of elements in this list 044 * @see ReadOnlyArrayList 045 */ 046@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="JDHBI_BUILDER") 047public final class ROArrayListBuilder<E> 048 extends ArrayList<E> 049 implements RandomAccess, Cloneable, Serializable 050{ 051 // ******************************************************************************************** 052 // ******************************************************************************************** 053 // Fields & Builder Stuff 054 // ******************************************************************************************** 055 // ******************************************************************************************** 056 057 058 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 059 protected static final long serialVersionUID = 1; 060 061 // Exception messages need this 062 private static final String ROAL = "ArrayList"; 063 064 private boolean built = false; 065 066 // Mimics the C++ Concept of "Friend Class". This badge is utilized by the "build()" method 067 // directly below this inner-class declaration. It is the only place where this declaration is 068 // actually used anywhere. This prohibits access to the constructor that is used to anybody 069 // else 070 071 static class AccessBadge { private AccessBadge() { } } 072 private static final AccessBadge friendClassBadge = new AccessBadge(); 073 074 /** 075 * Simply transfers {@code 'this'} instance' internal {@code ArrayList} to the 076 * {@code ReadOnlyArrayList} Wrapper-Class. 077 * 078 * @return a newly constructed {@code ReadOnlyArrayList} "Wrapper-Class", shielding the 079 * internal {@code 'arrayList'} private-field from any modification. 080 */ 081 public ReadOnlyArrayList<E> build() 082 { 083 super.trimToSize(); 084 this.built = true; 085 086 return (size() == 0) 087 ? ReadOnlyArrayList.emptyROAL() 088 : new ReadOnlyArrayList<>(this, friendClassBadge); 089 } 090 091 092 // ******************************************************************************************** 093 // ******************************************************************************************** 094 // Modified Constructors 095 // ******************************************************************************************** 096 // ******************************************************************************************** 097 098 099 /** 100 * Constructs an empty {@code ROArrayListBuilder} with the specified initial capacity. 101 * @param initialCapacity the initial capacity of the list 102 * @throws IllegalArgumentException if the specified initial capacity is negative 103 */ 104 public ROArrayListBuilder(int initialCapacity) 105 { super(initialCapacity); } 106 107 /** Constructs an empty list with an initial capacity of ten. */ 108 public ROArrayListBuilder() 109 { super(); } 110 111 /** 112 * Constructs a {@code ROArrayListBuilder} containing the elements of the specified collection, 113 * in the order they are returned by the collection's iterator. 114 * 115 * @param c the collection whose elements are to be placed into this list 116 * @throws NullPointerException if the specified collection is null 117 */ 118 public ROArrayListBuilder(Collection<? extends E> c) 119 { super(c); } 120 121 122 // ******************************************************************************************** 123 // ******************************************************************************************** 124 // Original JDK Methods 125 // ******************************************************************************************** 126 // ******************************************************************************************** 127 128 129 /** 130 * Trims the capacity of this {@code ArrayList} instance to be the list's current size. An 131 * application can use this operation to minimize the storage of an {@code ArrayList} instance. 132 * 133 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 134 */ 135 public void trimToSize() 136 { 137 if (this.built) throw new AttemptedModificationException(ROAL); 138 super.trimToSize(); 139 } 140 141 /** 142 * Increases the capacity of this {@code ArrayList} instance, if necessary, to ensure that it 143 * can hold at least the number of elements specified by the minimum capacity argument. 144 * 145 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 146 * 147 * @param minCapacity the desired minimum capacity 148 */ 149 public void ensureCapacity(int minCapacity) 150 { 151 if (this.built) throw new AttemptedModificationException(ROAL); 152 super.ensureCapacity(minCapacity); 153 } 154 155 /** 156 * Replaces the element at the specified position in this list with the specified element. 157 * 158 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 159 * 160 * @param index index of the element to replace 161 * @param element element to be stored at the specified position 162 * @return the element previously at the specified position 163 * 164 * @throws IndexOutOfBoundsException if the index is out of range 165 * {@code (index < 0 || index > size())} 166 */ 167 public E set(int index, E element) 168 { 169 if (this.built) throw new AttemptedModificationException(ROAL); 170 return super.set(index, element); 171 } 172 173 /** 174 * Appends the specified element to the end of this list. 175 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 176 * @param e element to be appended to this list 177 * @return {@code TRUE} (as specified by {@code Collection.add}) 178 */ 179 public boolean add(E e) 180 { 181 if (this.built) throw new AttemptedModificationException(ROAL); 182 return super.add(e); 183 } 184 185 /** 186 * Inserts the specified element at the specified position in this list. Shifts the element 187 * currently at that position (if any) and any subsequent elements to the right (adds one to 188 * their indices). 189 * 190 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 191 * 192 * @param index index at which the specified element is to be inserted 193 * @param element element to be inserted 194 * 195 * @throws IndexOutOfBoundsException if the index is out of range 196 * {@code (index < 0 || index >= size())} 197 */ 198 public void add(int index, E element) 199 { 200 if (this.built) throw new AttemptedModificationException(ROAL); 201 super.add(index, element); 202 } 203 204 /** 205 * Removes the element at the specified position in this list. Shifts any subsequent elements 206 * to the left (subtracts one from their indices). 207 * 208 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 209 * 210 * @param index the index of the element to be removed 211 * @return the element that was removed from the list 212 * 213 * @throws IndexOutOfBoundsException if the index is out of range 214 * {@code (index < 0 || index >= size())} 215 */ 216 public E remove(int index) 217 { 218 if (this.built) throw new AttemptedModificationException(ROAL); 219 return super.remove(index); 220 } 221 222 /** 223 * Removes the first occurrence of the specified element from this list, if it is present. If 224 * the list does not contain the element, it is unchanged. More formally, removes the element 225 * with the lowest index {@code i} such that {@code Objects.equals(o, get(i))} (if such an 226 * element exists). Returns {@code TRUE} if this list contained the specified element (or 227 * equivalently, if this list changed as a result of the call). 228 * 229 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 230 * 231 * @param o element to be removed from this list, if present 232 * @return {@code TRUE} if this list contained the specified element 233 */ 234 public boolean remove(Object o) 235 { 236 if (this.built) throw new AttemptedModificationException(ROAL); 237 return super.remove(o); 238 } 239 240 /** 241 * Removes all of the elements from this list. The list will be empty after this call returns. 242 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 243 */ 244 public void clear() 245 { 246 if (this.built) throw new AttemptedModificationException(ROAL); 247 super.clear(); 248 } 249 250 /** 251 * Appends all of the elements in the specified collection to the end of this list, in the 252 * order that they are returned by the specified collection's Iterator. The behavior of this 253 * operation is undefined if the specified collection is modified while the operation is in 254 * progress. (This implies that the behavior of this call is undefined if the specified 255 * collection is this list, and this list is nonempty.) 256 * 257 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 258 * 259 * @param c collection containing elements to be added to this list 260 * @return {@code TRUE} if this list changed as a result of the call 261 * @throws NullPointerException if the specified collection is null 262 */ 263 public boolean addAll(Collection<? extends E> c) 264 { 265 if (this.built) throw new AttemptedModificationException(ROAL); 266 return super.addAll(c); 267 } 268 269 /** 270 * Inserts all of the elements in the specified collection into this list, starting at the 271 * specified position. Shifts the element currently at that position (if any) and any 272 * subsequent elements to the right (increases their indices). The new elements will appear in 273 * the list in the order that they are returned by the specified collection's iterator. 274 * 275 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 276 * 277 * @param index index at which to insert the first element from the specified collection 278 * @param c collection containing elements to be added to this list 279 * @return {@code TRUE} if this list changed as a result of the call 280 * @throws NullPointerException if the specified collection is null 281 * 282 * @throws IndexOutOfBoundsException if the index is out of range 283 * {@code (index < 0 || index > size())} 284 */ 285 public boolean addAll(int index, Collection<? extends E> c) 286 { 287 if (this.built) throw new AttemptedModificationException(ROAL); 288 return super.addAll(index, c); 289 } 290 291 /** 292 * Removes from this list all of its elements that are contained in the specified collection. 293 * 294 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 295 * 296 * @param c collection containing elements to be removed from this list 297 * @return {@code TRUE} if this list changed as a result of the call 298 * 299 * @throws ClassCastException if the class of an element of this list is incompatible with the 300 * specified collection 301 * (<a href="Collection.html#optional-restrictions">optional</a>) 302 * 303 * @throws NullPointerException if this list contains a null element and the specified 304 * collection does not permit null elements 305 * (<a href="Collection.html#optional-restrictions">optional</a>), 306 * or if the specified collection is null 307 * 308 * @see ReadOnlyCollection#contains(Object) 309 */ 310 public boolean removeAll(Collection<?> c) 311 { 312 if (this.built) throw new AttemptedModificationException(ROAL); 313 return super.removeAll(c); 314 } 315 316 /** 317 * Retains only the elements in this list that are contained in the specified collection. In 318 * other words, removes from this list all of its elements that are not contained in the 319 * specified collection. 320 * 321 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 322 * 323 * @param c collection containing elements to be retained in this list 324 * @return {@code TRUE} if this list changed as a result of the call 325 * 326 * @throws ClassCastException if the class of an element of this list is incompatible with the 327 * specified collection 328 * (<a href="Collection.html#optional-restrictions">optional</a>) 329 * 330 * @throws NullPointerException if this list contains a null element and the specified 331 * collection does not permit null elements 332 * (<a href="Collection.html#optional-restrictions">optional</a>), 333 * or if the specified collection is null 334 * 335 * @see ReadOnlyCollection#contains(Object) 336 */ 337 public boolean retainAll(Collection<?> c) 338 { 339 if (this.built) throw new AttemptedModificationException(ROAL); 340 return super.retainAll(c); 341 } 342 343 /** 344 * Removes all of the elements of this collection that satisfy the given predicate. Errors or 345 * runtime exceptions thrown during iteration or by the predicate are relayed to the caller. 346 * 347 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 348 * 349 * @param filter a predicate which returns true for elements to be removed 350 * @return {@code TRUE} if any elements were removed 351 * @throws NullPointerException If parameter {@code 'filter'} has been passed null. 352 */ 353 public boolean removeIf(Predicate<? super E> filter) 354 { 355 if (this.built) throw new AttemptedModificationException(ROAL); 356 return super.removeIf(filter); 357 } 358 359 /** 360 * Replaces each element of this list with the result of applying the operator to that element. 361 * Errors or runtime exceptions thrown by the operator are relayed to the caller. 362 * 363 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 364 * 365 * @param operator the operator to apply to each element 366 * 367 * @throws NullPointerException - if the specified operator is null or if the operator result 368 * is a null value and this list does not permit null elements (optional) 369 */ 370 public void replaceAll(UnaryOperator<E> operator) 371 { 372 if (this.built) throw new AttemptedModificationException(ROAL); 373 super.replaceAll(operator); 374 } 375 376 /** 377 * Sorts this list according to the order induced by the specified Comparator. The sort is 378 * stable: this method must not reorder equal elements. 379 * 380 * <BR /><BR />All elements in this list must be mutually comparable using the specified 381 * comparator (that is, {@code c.compare(e1, e2)} must not throw a {@code ClassCastException} 382 * for any elements e1 and e2 in the list). 383 * 384 * <BR /><BR />If the specified comparator is null then all elements in this list must 385 * implement the Comparable interface and the elements' natural ordering should be used. 386 * 387 * <BR /><BR />This list must be modifiable, but need not be resizable. 388 * 389 * <EMBED DATA-TYPE=ArrayList CLASS='external-html' DATA-FILE-ID=MUTATOR> 390 * 391 * @param c the Comparator used to compare list elements. A null value indicates that the 392 * elements' natural ordering should be used 393 * 394 * @throws ClassCastException if the list contains elements that are not mutually comparable 395 * using the specified comparator 396 * 397 * @throws IllegalArgumentException (optional) if the comparator is found to violate the 398 * {@code Comparator} contract 399 */ 400 public void sort(Comparator<? super E> c) 401 { 402 if (this.built) throw new AttemptedModificationException(ROAL); 403 super.sort(c); 404 } 405 406 407 // ******************************************************************************************** 408 // ******************************************************************************************** 409 // Methods inherited from class java.util.ArrayList 410 // ******************************************************************************************** 411 // ******************************************************************************************** 412 413 414 // clone, forEach, hashCode, iterator, listIterator, listIterator, removeRange, spliterator, 415 // subList, toArray, toArray 416 // 417 // Introspection Only: clone, forEach, hashCode, spliterator, toArray, toArray 418 // Mutator or Potential Mutator: ilterator, listIterator, listIterator, subList 419 // Protected (not-needed) Mutator: removeRange 420 // 421 // *** OTHER INHERITED METHODS - ALL READ-ONLY METHODS *** 422 // 423 // Methods inherited from class java.util.AbstractCollection: containsAll, toString 424 // Methods inherited from interface java.util.Collection: parallelStream, stream, toArray 425 // Methods inherited from interface java.util.List: containsAll 426 427 /** 428 * Restricts a back-door into the underlying data-structure. 429 * <EMBED CLASS='external-html'DATA-RET_TYPE=Iterator DATA-FILE-ID=UNMODIFIABLE> 430 * @return a {@code java.util.Iterator} that cannot modify this {@code ArrayList-Builder} 431 */ 432 public RemoveUnsupportedIterator<E> iterator() 433 { return new RemoveUnsupportedIterator<>(super.iterator()); } 434 435 /** 436 * Restricts a back-door into the underlying data-structure. 437 * <EMBED CLASS='external-html'DATA-RET_TYPE=ListIterator DATA-FILE-ID=UNMODIFIABLE> 438 * @return a {@code java.util.ListIterator} that cannot modify this {@code ArrayList-Builder} 439 */ 440 public ListIterator<E> listIterator() 441 { return ROHelpers.removeUnsupportedListIterator(super.listIterator()); } 442 443 ListIterator<E> _listIterator(ReadOnlyArrayList.AccessBadge friendClassBadge) 444 { return super.listIterator(); } 445 446 /** 447 * Restricts a back-door into the underlying data-structure. 448 * <EMBED CLASS='external-html'DATA-RET_TYPE=ListIterator DATA-FILE-ID=UNMODIFIABLE> 449 * @return a {@code java.util.ListIterator} that cannot modify this {@code ArrayList-Builder} 450 */ 451 public ListIterator<E> listIterator(int index) 452 { return ROHelpers.removeUnsupportedListIterator(super.listIterator(index)); } 453 454 ListIterator<E> _listIterator(int index, ReadOnlyArrayList.AccessBadge friendClassBadge) 455 { return super.listIterator(index); } 456 457 /** 458 * Restricts a back-door into the underlying data-structure. 459 * <EMBED CLASS='external-html'DATA-RET_TYPE=List DATA-FILE-ID=UNMODIFIABLE> 460 * @return a {@code java.util.List} that cannot modify this {@code ArrayList-Builder} 461 */ 462 public List<E> subList(int fromIndex, int toIndex) 463 { return Collections.unmodifiableList(super.subList(fromIndex, toIndex)); } 464 465 List<E> _subList(int fromIndex, int toIndex, ReadOnlyArrayList.AccessBadge friendClassBadge) 466 { return super.subList(fromIndex, toIndex); } 467 468 469 // ******************************************************************************************** 470 // ******************************************************************************************** 471 // java.lang.Object & Cloneable 472 // ******************************************************************************************** 473 // ******************************************************************************************** 474 475 476 /** 477 * Compares the specified Object with this Builder for equality, as per the definition in the 478 * original class {@code java.util.ArrayList}. Ignores the private field {@code 'built'}. If 479 * {@code 'this'} has not been built, but {@code 'o'} has been, that fact is ignored during the 480 * equality-comparison. 481 * 482 * @param o object to be compared for equality with this {@code ROArrayListBuilder} instance 483 * @return true if the specified Object is equal to this Builder 484 */ 485 public boolean equals(Object o) 486 { 487 if (this == o) return true; 488 if (! (o instanceof ROArrayListBuilder)) return false; 489 return super.equals((ArrayList) o); 490 } 491 492 /** 493 * Clones this instance' of {@code ROArrayListBuilder}. 494 * 495 * <BR /><BR />The clone that's returned has had it's internal {@code 'built'} boolean-flag set 496 * {@code FALSE} 497 * 498 * @return a clone of this builder 499 */ 500 public synchronized ROArrayListBuilder<E> clone() 501 { return new ROArrayListBuilder<>(this); } 502 503 private ROArrayListBuilder(ROArrayListBuilder<E> roalb) 504 { super(roalb); this.built=false; } 505}