Coverage Report - jaggregate.OrderedCollection
 
Classes in this File Line Coverage Branch Coverage Complexity
OrderedCollection
100%
273/273
100%
29/29
0
OrderedCollection$1
100%
3/3
N/A
0
OrderedCollection$2
100%
3/3
N/A
0
OrderedCollection$3
100%
3/3
N/A
0
OrderedCollection$4
100%
3/3
N/A
0
OrderedCollection$5
100%
5/5
N/A
0
OrderedCollection$6
100%
5/5
N/A
0
OrderedCollection$7
100%
5/5
N/A
0
OrderedCollection$8
100%
5/5
N/A
0
 
 1  
 /*
 2  
  Copyright 2004-2008 Paul R. Holser, Jr.  All rights reserved.
 3  
  Licensed under the Academic Free License version 3.0
 4  
  */
 5  
 
 6  
 package jaggregate;
 7  
 
 8  
 import java.io.IOException;
 9  
 import java.io.ObjectInputStream;
 10  
 import java.io.ObjectOutputStream;
 11  
 import java.io.Serializable;
 12  
 import java.lang.reflect.Array;
 13  
 import java.util.NoSuchElementException;
 14  
 import static java.lang.Math.*;
 15  
 import static java.lang.System.*;
 16  
 
 17  
 import jaggregate.internal.Casting;
 18  
 import jaggregate.internal.ReadOnlySequences;
 19  
 import static jaggregate.internal.ArgumentChecks.*;
 20  
 import static jaggregate.internal.ReadOnlySequences.*;
 21  
 
 22  
 /**
 23  
  * Represents an ordered, variable-sized collection of objects, where elements may be
 24  
  * added, removed, or inserted, and can be accessed using external integer keys.
 25  
  *
 26  
  * @param <E> a restriction on the types of elements that may be included in the
 27  
  * collection
 28  
  *
 29  
  * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
 30  
  * @version $Id: OrderedCollection.java,v 1.8 2008/10/03 19:01:23 pholser Exp $
 31  
  */
 32  2787
 public class OrderedCollection<E> extends AbstractExtensibleCollection<E>
 33  
     implements ContractibleSequence<E>, Sequence<E>, Serializable {
 34  
 
 35  
     private static final int LEFT_BOUND = -2;
 36  
     private static final long serialVersionUID = -1L;
 37  
     private static final int DEFAULT_INITIAL_CAPACITY = 10;
 38  
 
 39  
     private transient Object[] storage;
 40  
     private int numberOfElements;
 41  
 
 42  
     /**
 43  
      * Creates an empty ordered collection.
 44  
      */
 45  
     public OrderedCollection() {
 46  6920
         this( DEFAULT_INITIAL_CAPACITY );
 47  6920
     }
 48  
 
 49  
     /**
 50  
      * Creates an ordered collection containing the elements in the given collection.
 51  
      *
 52  
      * @param elements elements to add to the new ordered collection
 53  
      * @throws NullPointerException if {@code elements} is {@code null}
 54  
      */
 55  
     public OrderedCollection( Collection<? extends E> elements ) {
 56  193
         this();
 57  193
         addAll( elements );
 58  192
     }
 59  
 
 60  
     /**
 61  
      * Creates an ordered collection containing the elements in the given array.
 62  
      *
 63  
      * @param elements elements to add to the new ordered collection
 64  
      * @throws NullPointerException if {@code elements} is {@code null}
 65  
      */
 66  
     public OrderedCollection( E... elements ) {
 67  531
         this();
 68  531
         addAll( elements );
 69  530
     }
 70  
 
 71  
     /**
 72  
      * Creates an ordered collection containing the elements in the given iterable
 73  
      * object.
 74  
      *
 75  
      * @param elements elements to add to the new ordered collection
 76  
      * @throws NullPointerException if {@code elements} is {@code null}
 77  
      */
 78  
     public OrderedCollection( Iterable<? extends E> elements ) {
 79  144
         this();
 80  144
         addAll( elements );
 81  143
     }
 82  
 
 83  
     /**
 84  
      * Creates an empty ordered collection with the given initial capacity.
 85  
      *
 86  
      * @param capacity the initial capacity
 87  
      * @throws IllegalArgumentException if {@code capacity <= 0}
 88  
      */
 89  6922
     public OrderedCollection( int capacity ) {
 90  6922
         if ( capacity <= 0 )
 91  1
             throw new IllegalArgumentException( "non-positive capacity: " + capacity );
 92  
 
 93  6921
         storage = new Object[ capacity ];
 94  6921
         numberOfElements = 0;
 95  6921
     }
 96  
 
 97  
     /**
 98  
      * Creates an empty ordered collection.
 99  
      *
 100  
      * @param <T> the type of elements allowed in the new ordered collection
 101  
      * @return a new empty ordered collection
 102  
      */
 103  
     public static <T> OrderedCollection<T> emptyOrderedCollection() {
 104  6010
         return new OrderedCollection<T>();
 105  
     }
 106  
 
 107  
     /**
 108  
      * Creates an ordered collection containing the elements in the given collection.
 109  
      *
 110  
      * @param <T> the type of elements allowed in the new ordered collection
 111  
      * @param elements elements to add to the new ordered collection
 112  
      * @return the new ordered collection
 113  
      * @throws NullPointerException if {@code elements} is {@code null}
 114  
      */
 115  
     public static <T> OrderedCollection<T> orderedCollectionFrom(
 116  
         Collection<? extends T> elements ) {
 117  
 
 118  181
         return new OrderedCollection<T>( elements );
 119  
     }
 120  
 
 121  
     /**
 122  
      * Creates an ordered collection containing the elements in the given array.
 123  
      *
 124  
      * @param <T> the type of elements allowed in the new ordered collection
 125  
      * @param elements elements to add to the new ordered collection
 126  
      * @return a new ordered collection
 127  
      * @throws NullPointerException if {@code elements} is {@code null}
 128  
      */
 129  
     public static <T> OrderedCollection<T> orderedCollectionFrom( T[] elements ) {
 130  530
         return new OrderedCollection<T>( elements );
 131  
     }
 132  
 
 133  
     /**
 134  
      * Creates an ordered collection containing the given elements.
 135  
      *
 136  
      * @param <T> the type of elements allowed in the new ordered collection
 137  
      * @param newElement first new element to ordered collection
 138  
      * @param restOfNewElements remainder of the elements to ordered collection
 139  
      * @return a new ordered collection
 140  
      * @throws NullPointerException if {@code restOfNewElements} is {@code null}
 141  
      * @throws IllegalArgumentException if any of the new elements is found to violate
 142  
      * restrictions on the characteristics of valid elements
 143  
      * @see #addAll(Collection)
 144  
      */
 145  
     public static <T> OrderedCollection<T> orderedCollectionWith( T newElement,
 146  
         T... restOfNewElements ) {
 147  
 
 148  1608
         OrderedCollection<T> ordered = emptyOrderedCollection();
 149  1608
         ordered.add( newElement );
 150  1608
         ordered.addAll( restOfNewElements );
 151  
 
 152  1608
         return ordered;
 153  
     }
 154  
 
 155  
     /**
 156  
      * Creates an ordered collection containing the elements in the given iterable
 157  
      * object.
 158  
      *
 159  
      * @param <T> the type of elements allowed in the new ordered collection
 160  
      * @param elements elements to add to the new ordered collection
 161  
      * @return a new ordered collection
 162  
      * @throws NullPointerException if {@code elements} is {@code null}
 163  
      */
 164  
     public static <T> OrderedCollection<T> orderedCollectionFrom(
 165  
         Iterable<? extends T> elements ) {
 166  
 
 167  144
         return new OrderedCollection<T>( elements );
 168  
     }
 169  
 
 170  
     /**
 171  
      * {@inheritDoc}
 172  
      */
 173  
     @Override
 174  
     public Object[] toArray( Class<? super E> componentClass ) {
 175  23
         Object[] asArray = (Object[]) Array.newInstance( componentClass, size() );
 176  23
         arraycopy( storage, 0, asArray, 0, size() );
 177  
 
 178  23
         return asArray;
 179  
     }
 180  
 
 181  
     /**
 182  
      * {@inheritDoc}
 183  
      * <p/>
 184  
      * Answers self.
 185  
      */
 186  
     @Override
 187  
     public OrderedCollection<E> toOrderedCollection() {
 188  1
         return this;
 189  
     }
 190  
 
 191  
     /**
 192  
      * {@inheritDoc}
 193  
      */
 194  
     @Override
 195  
     public <R> OrderedCollection<R> collect(
 196  
         UnaryFunctor<? super E, ? extends R> transformer ) {
 197  
 
 198  15
         return (OrderedCollection<R>) super.collect( transformer );
 199  
     }
 200  
 
 201  
     /**
 202  
      * {@inheritDoc}
 203  
      */
 204  
     public void forEachDo( UnaryFunctor<? super E, ?> operation ) {
 205  1588
         ensureNotNull( operation, OPERATION );
 206  
 
 207  6040
         for ( int i = 0; i < size(); ++i )
 208  4616
             operation.evaluate( at( i ) );
 209  1424
     }
 210  
 
 211  
     /**
 212  
      * {@inheritDoc}
 213  
      */
 214  
     @Override
 215  
     public OrderedCollection<E> reject( UnaryCondition<? super E> discriminator ) {
 216  27
         return (OrderedCollection<E>) super.reject( discriminator );
 217  
     }
 218  
 
 219  
     /**
 220  
      * {@inheritDoc}
 221  
      */
 222  
     @Override
 223  
     public OrderedCollection<E> select( UnaryCondition<? super E> discriminator ) {
 224  27
         return (OrderedCollection<E>) super.select( discriminator );
 225  
     }
 226  
 
 227  
     /**
 228  
      * {@inheritDoc}
 229  
      */
 230  
     public int size() {
 231  80720
         return numberOfElements;
 232  
     }
 233  
 
 234  
     /**
 235  
      * {@inheritDoc}
 236  
      */
 237  
     public int findFirst( UnaryCondition<? super E> discriminator ) {
 238  31
         return ReadOnlySequences.findFirst( this, discriminator );
 239  
     }
 240  
 
 241  
     /**
 242  
      * {@inheritDoc}
 243  
      */
 244  
     public int findLast( UnaryCondition<? super E> discriminator ) {
 245  41
         return ReadOnlySequences.findLast( this, discriminator );
 246  
     }
 247  
 
 248  
     /**
 249  
      * {@inheritDoc}
 250  
      */
 251  
     public void forEachInReverseDo( UnaryFunctor<? super E, ?> operation ) {
 252  74
         ReadOnlySequences.forEachInReverseDo( this, operation );
 253  34
     }
 254  
 
 255  
     /**
 256  
      * {@inheritDoc}
 257  
      */
 258  
     public E first() {
 259  117
         ensureNotEmpty();
 260  
 
 261  116
         return at( 0 );
 262  
     }
 263  
 
 264  
     /**
 265  
      * {@inheritDoc}
 266  
      */
 267  
     public void forEachInRangeDo( int start, int stop,
 268  
         UnaryFunctor<? super E, ?> operation ) {
 269  
 
 270  247
         ReadOnlySequences.forEachInRangeDo( this, start, stop, operation );
 271  220
     }
 272  
 
 273  
     /**
 274  
      * {@inheritDoc}
 275  
      */
 276  
     public void forEachInRangeDoWithIndex( int start, int stop,
 277  
         BinaryFunctor<? super Integer, ? super E, ?> operation ) {
 278  
 
 279  222
         ReadOnlySequences.forEachInRangeDoWithIndex( this, start, stop, operation );
 280  195
     }
 281  
 
 282  
     /**
 283  
      * {@inheritDoc}
 284  
      */
 285  
     public int indexOf( E target ) {
 286  294
         return ReadOnlySequences.indexOf( this, target );
 287  
     }
 288  
 
 289  
     /**
 290  
      * {@inheritDoc}
 291  
      */
 292  
     public int indexOf( ReadOnlySequence<? extends E> targetSequence, int start ) {
 293  54
         return ReadOnlySequences.indexOf( this, targetSequence, start );
 294  
     }
 295  
 
 296  
     /**
 297  
      * {@inheritDoc}
 298  
      */
 299  
     public void doWithIndex( BinaryFunctor<? super Integer, ? super E, ?> operation ) {
 300  2359
         ReadOnlySequences.doWithIndex( this, operation );
 301  2083
     }
 302  
 
 303  
     /**
 304  
      * {@inheritDoc}
 305  
      */
 306  
     public E last() {
 307  30
         ensureNotEmpty();
 308  
 
 309  29
         return at( size() - 1 );
 310  
     }
 311  
 
 312  
     /**
 313  
      * {@inheritDoc}
 314  
      * <p/>
 315  
      * {@code newElement} is added to the end of this collection's elements so that it
 316  
      * becomes the {@linkplain #last() last} element in the traversal order.
 317  
      * This message is equivalent to {@link #addLast(Object) addLast} for this
 318  
      * collection with {@code newElement} as the parameter.
 319  
      */
 320  
     public void add( E newElement ) {
 321  15348
         addLast( newElement );
 322  15348
     }
 323  
 
 324  
     /**
 325  
      * {@inheritDoc}
 326  
      */
 327  
     public boolean remove( E oldElement ) {
 328  56
         int indexOfOldElement = indexOf( oldElement );
 329  
 
 330  56
         if ( indexOfOldElement == -1 )
 331  26
             return false;
 332  
 
 333  30
         removeAt( indexOfOldElement );
 334  30
         return true;
 335  
     }
 336  
 
 337  
     /**
 338  
      * {@inheritDoc}
 339  
      */
 340  
     @Override
 341  
     public boolean removeIf( UnaryCondition<? super E> discriminator ) {
 342  23
         ensureNotNull( discriminator, DISCRIMINATOR );
 343  
 
 344  22
         boolean removalOccurred = false;
 345  
 
 346  22
         int i = 0;
 347  154
         while ( i < size() ) {
 348  132
             if ( discriminator.matches( at( i ) ) ) {
 349  60
                 removalOccurred = true;
 350  60
                 removeAt( i );
 351  
             }
 352  
             else
 353  72
                 ++i;
 354  
         }
 355  
 
 356  22
         return removalOccurred;
 357  
     }
 358  
 
 359  
     /**
 360  
      * {@inheritDoc}
 361  
      */
 362  
     @Override
 363  
     public boolean retainIf( UnaryCondition<? super E> discriminator ) {
 364  5
         ensureNotNull( discriminator, DISCRIMINATOR );
 365  
 
 366  4
         boolean removalOccurred = false;
 367  
 
 368  4
         int i = 0;
 369  28
         while ( i < size() ) {
 370  24
             if ( discriminator.matches( at( i ) ) )
 371  18
                 ++i;
 372  
             else {
 373  6
                 removalOccurred = true;
 374  6
                 removeAt( i );
 375  
             }
 376  
         }
 377  
 
 378  4
         return removalOccurred;
 379  
     }
 380  
 
 381  
     /**
 382  
      * {@inheritDoc}
 383  
      */
 384  
     public E removeAt( int index ) {
 385  119
         ensureIndexIsValid( index, "removal" );
 386  
 
 387  112
         E removedElement = Casting.<E>cast( storage[ index ] );
 388  112
         --numberOfElements;
 389  112
         arraycopy( storage, index + 1, storage, index, size() - index );
 390  
 
 391  112
         return removedElement;
 392  
     }
 393  
 
 394  
     /**
 395  
      * {@inheritDoc}
 396  
      */
 397  
     public E removeFirst() {
 398  5
         ensureNotEmpty();
 399  
 
 400  2
         return removeAt( 0 );
 401  
     }
 402  
 
 403  
     /**
 404  
      * {@inheritDoc}
 405  
      */
 406  
     public E removeLast() {
 407  5
         ensureNotEmpty();
 408  
 
 409  2
         return removeAt( size() - 1 );
 410  
     }
 411  
 
 412  
     /**
 413  
      * {@inheritDoc}
 414  
      */
 415  
     public OrderedCollection<E> concat( ReadOnlySequence<? extends E> otherSequence ) {
 416  15
         return ReadOnlySequences.concat( this, otherSequence );
 417  
     }
 418  
 
 419  
     /**
 420  
      * {@inheritDoc}
 421  
      */
 422  
     public E after( E target ) {
 423  69
         int indexOfTarget = ensureIndexOfElementIsNot( target, size() - 1 );
 424  
 
 425  39
         return at( indexOfTarget + 1 );
 426  
     }
 427  
 
 428  
     /**
 429  
      * {@inheritDoc}
 430  
      */
 431  
     public E at( int index ) {
 432  29397
         ensureIndexIsValid( index, "search" );
 433  
 
 434  29382
         return Casting.<E>cast( storage[ index ] );
 435  
     }
 436  
 
 437  
     /**
 438  
      * {@inheritDoc}
 439  
      */
 440  
     public E before( E target ) {
 441  69
         int indexOfTarget = indexOf( target );
 442  69
         if ( indexOfTarget <= 0 )
 443  30
             throw new NoSuchElementException( "no element before " + target );
 444  
 
 445  39
         return at( indexOfTarget - 1 );
 446  
     }
 447  
 
 448  
     /**
 449  
      * {@inheritDoc}
 450  
      */
 451  
     public OrderedCollection<E> copyRange( int start, int stop ) {
 452  235
         return ReadOnlySequences.copyRange( this, start, stop );
 453  
     }
 454  
 
 455  
     /**
 456  
      * {@inheritDoc}
 457  
      */
 458  
     public OrderedCollection<E> copyWith( E newElement ) {
 459  23
         return ReadOnlySequences.copyWith( this, newElement );
 460  
     }
 461  
 
 462  
     /**
 463  
      * {@inheritDoc}
 464  
      */
 465  
     public OrderedCollection<E> copyWithout( E oldElement ) {
 466  77
         return ReadOnlySequences.copyWithout( this, oldElement );
 467  
     }
 468  
 
 469  
     /**
 470  
      * {@inheritDoc}
 471  
      */
 472  
     public OrderedCollection<E> reverse() {
 473  30
         return ReadOnlySequences.reverse( this );
 474  
     }
 475  
 
 476  
     /**
 477  
      * {@inheritDoc}
 478  
      */
 479  
     public <T> void doWithOthers( ReadOnlySequence<? extends T> otherSequence,
 480  
         BinaryFunctor<? super E, ? super T, ?> operation ) {
 481  
 
 482  33
         ReadOnlySequences.doWithOthers( this, otherSequence, operation );
 483  30
     }
 484  
 
 485  
     /**
 486  
      * {@inheritDoc}
 487  
      */
 488  
     public E putAt( int index, E newElement ) {
 489  1662
         ensureIndexIsValid( index, "insertion" );
 490  
 
 491  1643
         E previousElement = at( index );
 492  1643
         storage[ index ] = newElement;
 493  1643
         return previousElement;
 494  
     }
 495  
 
 496  
     /**
 497  
      * {@inheritDoc}
 498  
      */
 499  
     public void putAtAll( Collection<? extends Integer> indices, final E newElement ) {
 500  8
         indices.forEachDo( new UnaryFunctor<Integer, Void>() {
 501  15
             public Void evaluate( Integer argument ) {
 502  7
                 putAt( argument, newElement );
 503  3
                 return null;
 504  
             }
 505  
         } );
 506  3
     }
 507  
 
 508  
     /**
 509  
      * {@inheritDoc}
 510  
      */
 511  
     public void putAtAll( int[] indices, E newElement ) {
 512  12
         for ( int each : indices )
 513  8
             putAt( each, newElement );
 514  3
     }
 515  
 
 516  
     /**
 517  
      * {@inheritDoc}
 518  
      */
 519  
     public void putAtAll( Integer[] indices, E newElement ) {
 520  12
         for ( int each : indices )
 521  8
             putAt( each, newElement );
 522  3
     }
 523  
 
 524  
     /**
 525  
      * {@inheritDoc}
 526  
      */
 527  
     public void putAtAll( Iterable<? extends Integer> indices, E newElement ) {
 528  8
         for ( int each : indices )
 529  8
             putAt( each, newElement );
 530  3
     }
 531  
 
 532  
     /**
 533  
      * {@inheritDoc}
 534  
      */
 535  
     public void putAtAll( final E newElement ) {
 536  2
         doWithIndex( new BinaryFunctor<Integer, E, Void>() {
 537  4
             public Void evaluate( Integer first, E second ) {
 538  2
                 putAt( first, newElement );
 539  2
                 return null;
 540  
             }
 541  
         } );
 542  2
     }
 543  
 
 544  
     /**
 545  
      * {@inheritDoc}
 546  
      */
 547  
     public void replace( int start, int stop, final E replacement ) {
 548  9
         ensureIndexIsValid( start, STARTING_INDEX );
 549  6
         ensureIndexIsValid( stop, ENDING_INDEX );
 550  
 
 551  4
         forEachInRangeDoWithIndex( start, stop, new BinaryFunctor<Integer, E, Void>() {
 552  8
             public Void evaluate( Integer first, E second ) {
 553  4
                 putAt( first, replacement );
 554  4
                 return null;
 555  
             }
 556  
         } );
 557  4
     }
 558  
 
 559  
     /**
 560  
      * {@inheritDoc}
 561  
      */
 562  
     public void replaceRange( final int start, int stop,
 563  
         ReadOnlySequence<? extends E> replacements ) {
 564  
 
 565  11
         ensureNotNull( replacements, REPLACEMENT_SEQUENCE );
 566  10
         ensureIndexIsValid( start, STARTING_INDEX );
 567  7
         ensureIndexIsValid( stop, ENDING_INDEX );
 568  
 
 569  5
         if ( stop >= start ) {
 570  4
             if ( replacements.size() != stop - start + 1 ) {
 571  1
                 throw new IllegalArgumentException(
 572  
                     EXPECTED_SEQUENCE_SIZE
 573  
                         + ( stop - start + 1 )
 574  
                         + BUT_WAS
 575  
                         + replacements.size() );
 576  
             }
 577  
 
 578  3
             replacements.doWithIndex( new BinaryFunctor<Integer, E, Void>() {
 579  7
                 public Void evaluate( Integer first, E second ) {
 580  4
                     putAt( first + start, second );
 581  4
                     return null;
 582  
                 }
 583  
             } );
 584  
         }
 585  4
     }
 586  
 
 587  
     /**
 588  
      * {@inheritDoc}
 589  
      */
 590  
     public void replaceRange( int start, int stop,
 591  
         final ReadOnlySequence<? extends E> replacements, int replacementStart ) {
 592  
 
 593  16
         ensureNotNull( replacements, REPLACEMENT_SEQUENCE );
 594  15
         ensureIndexIsValid( start, STARTING_INDEX );
 595  12
         ensureIndexIsValid( stop, ENDING_INDEX );
 596  10
         checkIndexIsValidOn( replacements, replacementStart, "replacement starting" );
 597  
 
 598  8
         if ( stop >= start ) {
 599  7
             if ( replacements.size() != replacementStart + stop - start + 1 ) {
 600  2
                 throw new IllegalArgumentException(
 601  
                     "expecting replacement sequence of size "
 602  
                         + ( replacementStart + stop - start + 1 )
 603  
                         + BUT_WAS
 604  
                         + replacements.size() );
 605  
             }
 606  
 
 607  5
             final int[] replacementIndex = { replacementStart };
 608  
 
 609  5
             forEachInRangeDoWithIndex( start, stop,
 610  
                 new BinaryFunctor<Integer, E, Void>() {
 611  11
                     public Void evaluate( Integer first, E second ) {
 612  6
                         int whereToReplace = replacementIndex[ 0 ];
 613  6
                         ++replacementIndex[ 0 ];
 614  6
                         putAt( first, replacements.at( whereToReplace ) );
 615  6
                         return null;
 616  
                     }
 617  
                 }
 618  
             );
 619  
         }
 620  6
     }
 621  
 
 622  
     /**
 623  
      * Adds a new element to this collection immediately following the first element
 624  
      * which is equivalent to a given target.  An element immediately follows another
 625  
      * if its index is one greater than that of the other.  The order used to determine
 626  
      * which of this collection's elements is the first to equal {@code target} is
 627  
      * the traversal order defined by {@link #forEachDo(UnaryFunctor) forEachDo} for
 628  
      * this collection.
 629  
      *
 630  
      * @param newElement the element to add
 631  
      * @param target the element after which to add {@code newElement}
 632  
      * @throws NoSuchElementException if this collection does not {@linkplain
 633  
      * #includes(Object) include} {@code target}
 634  
      */
 635  
     public void addAfter( E newElement, E target ) {
 636  3
         int indexOfTarget = ensureElementIsPresent( target );
 637  2
         addAfterIndex( newElement, indexOfTarget );
 638  2
     }
 639  
 
 640  
     /**
 641  
      * Adds a new element to this collection immediately following the element at
 642  
      * the given index.  {@code newElement} is inserted at position {@code index + 1}.
 643  
      * If {@code index == -1}, {@code newElement} becomes the {@linkplain #first() first}
 644  
      * element of this collection.
 645  
      *
 646  
      * @param newElement the element to add
 647  
      * @param index the index after which to add {@code newElement}
 648  
      * @throws IndexOutOfBoundsException if {@code index < -1} or {@code index >=} this
 649  
      * collection's {@linkplain #size() size}.
 650  
      */
 651  
     public void addAfterIndex( E newElement, int index ) {
 652  10
         ensureIndexIsGreaterThan( index, LEFT_BOUND, ADDITION_INDEX );
 653  9
         ensureIndexIsLessThan( index, size(), ADDITION_INDEX );
 654  
 
 655  8
         if ( index == -1 )
 656  2
             addFirst( newElement );
 657  6
         else if ( index == size() - 1 )
 658  1
             addLast( newElement );
 659  
         else {
 660  5
             resizeIfNeeded();
 661  5
             arraycopy( storage, index + 1, storage, index + 2, size() - index - 1 );
 662  
 
 663  5
             putAt( index + 1, newElement );
 664  5
             ++numberOfElements;
 665  
         }
 666  8
     }
 667  
 
 668  
     /**
 669  
      * Adds a new element to this collection immediately preceding the first element
 670  
      * which is equivalent to a given target.  An element immediately precedes another
 671  
      * if its index is one less than that of the other.  The order used to determine
 672  
      * which of this collection's elements is the first to equal {@code target} is the
 673  
      * traversal order defined by {@link #forEachDo(UnaryFunctor) forEachDo} for this
 674  
      * collection.
 675  
      *
 676  
      * @param newElement the element to add
 677  
      * @param target the element before which to add {@code newElement}
 678  
      * @throws NoSuchElementException if this collection does not {@linkplain
 679  
      * #includes(Object) include} {@code target}
 680  
      */
 681  
     public void addBefore( E newElement, E target ) {
 682  3
         int indexOfTarget = ensureElementIsPresent( target );
 683  2
         addBeforeIndex( newElement, indexOfTarget );
 684  2
     }
 685  
 
 686  
     /**
 687  
      * Adds a new element to this collection immediately preceding the element at the
 688  
      * given index.  If {@code index ==} this collection's {@linkplain #size() size},
 689  
      * then {@code newElement} will become the {@linkplain #last() last} element of
 690  
      * this collection.
 691  
      *
 692  
      * @param newElement the element to add
 693  
      * @param index the before after which to add {@code newElement}
 694  
      * @throws IndexOutOfBoundsException if {@code index < 0} or {@code index >} this
 695  
      * collection's {@linkplain #size() size}.
 696  
      */
 697  
     public void addBeforeIndex( E newElement, int index ) {
 698  2483
         ensureIndexIsGreaterThan( index, -1, ADDITION_INDEX );
 699  2482
         ensureIndexIsLessThan( index, size() + 1, ADDITION_INDEX );
 700  
 
 701  2481
         if ( index == 0 )
 702  1039
             addFirst( newElement );
 703  1442
         else if ( index == size() )
 704  1000
             addLast( newElement );
 705  
         else {
 706  442
             resizeIfNeeded();
 707  442
             arraycopy( storage, index, storage, index + 1, size() - index );
 708  
 
 709  442
             putAt( index, newElement );
 710  442
             ++numberOfElements;
 711  
         }
 712  2481
     }
 713  
 
 714  
     /**
 715  
      * Adds each element of the given collection to this collection immediately after
 716  
      * the first element in this collection which is equivalent to a given target.
 717  
      * <p/>
 718  
      * The elements of {@code newElements} are added to this collection in the traversal
 719  
      * order defined by {@link #forEachDo(UnaryFunctor) forEachDo} for {@code
 720  
      * newElements}.  An element immediately follows another if its index is one greater
 721  
      * than that of the other.  The order used to determine which of this collection's
 722  
      * elements is the first to equal {@code target} is the traversal order defined by
 723  
      * {@link #forEachDo(UnaryFunctor) forEachDo} for this collection.
 724  
      *
 725  
      * @param newElements the elements to add
 726  
      * @param target the element after which to perform the additions
 727  
      * @throws NullPointerException if {@code newElements} is {@code null}
 728  
      * @throws NoSuchElementException if this collection does not {@linkplain
 729  
      * #includes(Object) include} {@code target}
 730  
      */
 731  
     public void addAllAfter( Collection<? extends E> newElements, E target ) {
 732  6
         int indexOfTarget = ensureElementIsPresent( target );
 733  3
         addAllAfterIndex( newElements, indexOfTarget );
 734  3
     }
 735  
 
 736  
     /**
 737  
      * @see #addAllAfter(Collection,Object)
 738  
      * @param newElements the elements to add
 739  
      * @param target the element after which to perform the additions
 740  
      * @throws NullPointerException if {@code newElements} is {@code null}
 741  
      * @throws NoSuchElementException if this collection does not {@linkplain
 742  
      * #includes(Object) include} {@code target}
 743  
      */
 744  
     public void addAllAfter( E[] newElements, E target ) {
 745  2
         addAllAfter( orderedCollectionFrom( newElements ), target );
 746  1
     }
 747  
 
 748  
     /**
 749  
      * @see #addAllAfter(Collection,Object)
 750  
      * @param newElements the elements to add
 751  
      * @param target the element after which to perform the additions
 752  
      * @throws NullPointerException if {@code newElements} is {@code null}
 753  
      * @throws NoSuchElementException if this collection does not {@linkplain
 754  
      * #includes(Object) include} {@code target}
 755  
      */
 756  
     public void addAllAfter( Iterable<? extends E> newElements, E target ) {
 757  2
         addAllAfter( orderedCollectionFrom( newElements ), target );
 758  1
     }
 759  
 
 760  
     /**
 761  
      * Adds each element of the given collection to this collection immediately
 762  
      * following the element at the given index.
 763  
      * <p/>
 764  
      * The elements of {@code newElements} are added to this collection in the traversal
 765  
      * order defined by {@link #forEachDo(UnaryFunctor) forEachDo} for {@code
 766  
      * newElements}.  {@code newElements} are inserted immediately after the element in
 767  
      * this collection at position {@code index}.  If {@code index == -1},
 768  
      * {@code newElements} are inserted at the beginning of this collection.
 769  
      *
 770  
      * @param newElements the elements to add
 771  
      * @param index the index after which to add {@code newElements}
 772  
      * @throws NullPointerException if {@code newElements} is {@code null}
 773  
      * @throws IndexOutOfBoundsException if {@code index < -1} or {@code index >=} this
 774  
      * collection's {@linkplain #size() size}
 775  
      */
 776  
     public void addAllAfterIndex( Collection<? extends E> newElements, final int index ) {
 777  18
         ensureIndexIsGreaterThan( index, LEFT_BOUND, ADDITION_INDEX );
 778  15
         ensureIndexIsLessThan( index, size(), ADDITION_INDEX );
 779  
 
 780  12
         if ( index == -1 )
 781  3
             addAllFirst( newElements );
 782  9
         else if ( index == size() - 1 )
 783  3
             addAllLast( newElements );
 784  
         else {
 785  6
             resizeIfNeeded( size() + newElements.size() );
 786  6
             arraycopy( storage, index + 1, storage, index + 1 + newElements.size(),
 787  
                 size() - index - 1 );
 788  
 
 789  6
             final int[] offset = { 0 };
 790  
 
 791  6
             newElements.forEachDo( new UnaryFunctor<E, Void>() {
 792  18
                 public Void evaluate( E argument ) {
 793  12
                     storage[ index + 1 + offset[ 0 ] ] = argument;
 794  12
                     ++offset[ 0 ];
 795  12
                     ++numberOfElements;
 796  12
                     return null;
 797  
                 }
 798  
             } );
 799  
         }
 800  12
     }
 801  
 
 802  
     /**
 803  
      * @see #addAllAfterIndex(Collection,int)
 804  
      * @param newElements the elements to add
 805  
      * @param index the index after which to add {@code newElements}
 806  
      * @throws NullPointerException if {@code newElements} is {@code null}
 807  
      * @throws IndexOutOfBoundsException if {@code index < -1} or {@code index >=} this
 808  
      * collection's {@linkplain #size() size}
 809  
      */
 810  
     public void addAllAfterIndex( E[] newElements, int index ) {
 811  5
         addAllAfterIndex( orderedCollectionFrom( newElements ), index );
 812  3
     }
 813  
 
 814  
     /**
 815  
      * @see #addAllAfterIndex(Collection,int)
 816  
      * @param newElements the elements to add
 817  
      * @param index the index after which to add {@code newElements}
 818  
      * @throws NullPointerException if {@code newElements} is {@code null}
 819  
      * @throws IndexOutOfBoundsException if {@code index < -1} or {@code index >=} this
 820  
      * collection's {@linkplain #size() size}
 821  
      */
 822  
     public void addAllAfterIndex( Iterable<? extends E> newElements, int index ) {
 823  5
         addAllAfterIndex( orderedCollectionFrom( newElements ), index );
 824  3
     }
 825  
 
 826  
     /**
 827  
      * Adds each element of the given collection to this collection immediately before
 828  
      * the first element in this collection which is equivalent to a given target.
 829  
      * <p/>
 830  
      * The elements of {@code newElements} are added to this collection in the traversal
 831  
      * order defined by {@link #forEachDo(UnaryFunctor) forEachDo} for {@code
 832  
      * newElements}.  An element immediately precedes another if its index is one
 833  
      * greater than that of the other.  The order used to determine which of this
 834  
      * collection's elements is the first to equal {@code target} is the traversal order
 835  
      * defined by {@link #forEachDo(UnaryFunctor) forEachDo} for this collection.
 836  
      *
 837  
      * @param newElements the elements to add
 838  
      * @param target the element before which to perform the additions
 839  
      * @throws NullPointerException if {@code newElements} is {@code null}
 840  
      * @throws NoSuchElementException if this collection does not {@linkplain
 841  
      * #includes(Object) include} {@code target}
 842  
      */
 843  
     public void addAllBefore( Collection<? extends E> newElements, E target ) {
 844  6
         int indexOfTarget = ensureElementIsPresent( target );
 845  3
         addAllBeforeIndex( newElements, indexOfTarget );
 846  3
     }
 847  
 
 848  
     /**
 849  
      * @see #addAllBefore(Collection,Object)
 850  
      * @param newElements the elements to add
 851  
      * @param target the element before which to perform the additions
 852  
      * @throws NullPointerException if {@code newElements} is {@code null}
 853  
      * @throws NoSuchElementException if this collection does not {@linkplain
 854  
      * #includes(Object) include} {@code target}
 855  
      */
 856  
     public void addAllBefore( E[] newElements, E target ) {
 857  2
         addAllBefore( orderedCollectionFrom( newElements ), target );
 858  1
     }
 859  
 
 860  
     /**
 861  
      * @see #addAllBefore(Collection,Object)
 862  
      * @param newElements the elements to add
 863  
      * @param target the element before which to perform the additions
 864  
      * @throws NullPointerException if {@code newElements} is {@code null}
 865  
      * @throws NoSuchElementException if this collection does not {@linkplain
 866  
      * #includes(Object) include} {@code target}
 867  
      */
 868  
     public void addAllBefore( Iterable<? extends E> newElements, E target ) {
 869  2
         addAllBefore( orderedCollectionFrom( newElements ), target );
 870  1
     }
 871  
 
 872  
     /**
 873  
      * Adds each element of the given collection to this collection immediately
 874  
      * preceding the element at the given index.
 875  
      * <p/>
 876  
      * The elements of {@code newElements} are added to this collection in the traversal
 877  
      * order defined by {@link #forEachDo(UnaryFunctor) forEachDo} for {@code
 878  
      * newElements}.  {@code newElements} are inserted immediately before the element in
 879  
      * this collection at position {@code index}.  If {@code index ==} this collection's
 880  
      * {@linkplain #size() size}, {@code newElements} are inserted at the end of this
 881  
      * collection.
 882  
      *
 883  
      * @param newElements the elements to add
 884  
      * @param index the index after which to add {@code newElements}
 885  
      * @throws NullPointerException if {@code newElements} is {@code null}
 886  
      * @throws IndexOutOfBoundsException if {@code index < 0} or {@code index >} this
 887  
      * collection's {@linkplain #size() size}
 888  
      */
 889  
     public void addAllBeforeIndex( Collection<? extends E> newElements,
 890  
         final int index ) {
 891  
 
 892  24
         ensureIndexIsGreaterThan( index, -1, ADDITION_INDEX );
 893  21
         ensureIndexIsLessThan( index, size() + 1, ADDITION_INDEX );
 894  
 
 895  18
         if ( index == 0 )
 896  12
             addAllFirst( newElements );
 897  6
         else if ( index == size() )
 898  3
             addAllLast( newElements );
 899  
         else {
 900  3
             resizeIfNeeded( size() + newElements.size() );
 901  3
             arraycopy( storage, index, storage, index + newElements.size(),
 902  
                 size() - index );
 903  
 
 904  3
             final int[] offset = { 0 };
 905  
 
 906  3
             newElements.forEachDo( new UnaryFunctor<E, Void>() {
 907  9
                 public Void evaluate( E argument ) {
 908  6
                     storage[ index + offset[ 0 ] ] = argument;
 909  6
                     ++offset[ 0 ];
 910  6
                     ++numberOfElements;
 911  6
                     return null;
 912  
                 }
 913  
             } );
 914  
         }
 915  18
     }
 916  
 
 917  
     /**
 918  
      * @see #addAllBeforeIndex(Collection,int)
 919  
      * @param newElements the elements to add
 920  
      * @param index the index after which to add {@code newElements}
 921  
      * @throws NullPointerException if {@code newElements} is {@code null}
 922  
      * @throws IndexOutOfBoundsException if {@code index < 0} or {@code index >} this
 923  
      * collection's {@linkplain #size() size}
 924  
      */
 925  
     public void addAllBeforeIndex( E[] newElements, int index ) {
 926  5
         addAllBeforeIndex( orderedCollectionFrom( newElements ), index );
 927  3
     }
 928  
 
 929  
     /**
 930  
      * @see #addAllBeforeIndex(Collection,int)
 931  
      * @param newElements the elements to add
 932  
      * @param index the index after which to add {@code newElements}
 933  
      * @throws NullPointerException if {@code newElements} is {@code null}
 934  
      * @throws IndexOutOfBoundsException if {@code index < 0} or {@code index >} this
 935  
      * collection's {@linkplain #size() size}
 936  
      */
 937  
     public void addAllBeforeIndex( Iterable<? extends E> newElements, int index ) {
 938  5
         addAllBeforeIndex( orderedCollectionFrom( newElements ), index );
 939  3
     }
 940  
 
 941  
     /**
 942  
      * Adds each element of the given collection to the beginning of this collection's
 943  
      * elements.
 944  
      * <p/>
 945  
      * This operation is equivalent to adding each successive element of {@code
 946  
      * newElements} to this collection using {@link #addFirst(Object) addFirst} with the
 947  
      * element as the parameter, where {@code newElements} are traversed in the order
 948  
      * specified by {@link #forEachInReverseDo(UnaryFunctor) forEachInReverseDo} for
 949  
      * {@code newElements}.
 950  
      *
 951  
      * @param newElements the elements to add
 952  
      * @throws NullPointerException if {@code newElements} is {@code null}
 953  
      */
 954  
     public void addAllFirst( Collection<? extends E> newElements ) {
 955  403
         ensureNotNull( newElements, "new elements" );
 956  
 
 957  402
         if ( !newElements.isEmpty() ) {
 958  402
             resizeIfNeeded( size() + newElements.size() );
 959  402
             arraycopy( storage, 0, storage, newElements.size(), size() );
 960  
         }
 961  
 
 962  402
         final int[] index = { 0 };
 963  402
         newElements.forEachDo( new UnaryFunctor<E, Void>() {
 964  1699
             public Void evaluate( E argument ) {
 965  1297
                 storage[ index[ 0 ] ] = argument;
 966  1297
                 ++index[ 0 ];
 967  1297
                 numberOfElements++;
 968  1297
                 return null;
 969  
             }
 970  
         } );
 971  402
     }
 972  
 
 973  
     /**
 974  
      * @see #addAllFirst(Collection)
 975  
      * @param newElements the elements to add
 976  
      * @throws NullPointerException if {@code newElements} is {@code null}
 977  
      */
 978  
     public void addAllFirst( E... newElements ) {
 979  129
         addAllFirst( orderedCollectionFrom( newElements ) );
 980  129
     }
 981  
 
 982  
     /**
 983  
      * @see #addAllFirst(Collection)
 984  
      * @param newElements the elements to add
 985  
      * @throws NullPointerException if {@code newElements} is {@code null}
 986  
      */
 987  
     public void addAllFirst( Iterable<? extends E> newElements ) {
 988  129
         addAllFirst( orderedCollectionFrom( newElements ) );
 989  129
     }
 990  
 
 991  
     /**
 992  
      * Adds each element of the given collection to the end of this collection's
 993  
      * elements.
 994  
      * <p/>
 995  
      * This operation is equivalent to adding each successive element of {@code
 996  
      * newElements} to this collection using {@link #addLast(Object) addLast} with the
 997  
      * element as the parameter, where {@code newElements} are traversed in the order
 998  
      * specified by {@link #forEachDo(UnaryFunctor) forEachDo} for {@code newElements}.
 999  
      *
 1000  
      * @param newElements the elements to add
 1001  
      * @throws NullPointerException if {@code newElements} is {@code null}
 1002  
      */
 1003  
     public void addAllLast( Collection<? extends E> newElements ) {
 1004  135
         addAll( newElements );
 1005  135
     }
 1006  
 
 1007  
     /**
 1008  
      * @see #addAllLast(Collection)
 1009  
      * @param newElements the elements to add
 1010  
      * @throws NullPointerException if {@code newElements} is {@code null}
 1011  
      */
 1012  
     public void addAllLast( E... newElements ) {
 1013  129
         addAll( newElements );
 1014  129
     }
 1015  
 
 1016  
     /**
 1017  
      * @see #addAllLast(Collection)
 1018  
      * @param newElements the elements to add
 1019  
      * @throws NullPointerException if {@code newElements} is {@code null}
 1020  
      */
 1021  
     public void addAllLast( Iterable<? extends E> newElements ) {
 1022  129
         addAll( newElements );
 1023  129
     }
 1024  
 
 1025  
     /**
 1026  
      * Adds a new element to the beginning of this collection's elements.
 1027  
      * {@code newElement} becomes the {@linkplain #first() first} element in the
 1028  
      * traversal order.
 1029  
      *
 1030  
      * @param newElement the element to add
 1031  
      */
 1032  
     public void addFirst( E newElement ) {
 1033  1074
         resizeIfNeeded();
 1034  1074
         arraycopy( storage, 0, storage, 1, size() );
 1035  1074
         ++numberOfElements;
 1036  1074
         putAt( 0, newElement );
 1037  1074
     }
 1038  
 
 1039  
     /**
 1040  
      * Adds a new element to the end of this collection's elements.  {@code newElement}
 1041  
      * becomes the {@linkplain #last() last} element in the traversal order.
 1042  
      *
 1043  
      * @param newElement the element to add
 1044  
      */
 1045  
     public void addLast( E newElement ) {
 1046  16382
         resizeIfNeeded();
 1047  16382
         storage[ numberOfElements ] = newElement;
 1048  16382
         ++numberOfElements;
 1049  16382
     }
 1050  
 
 1051  
     /**
 1052  
      * {@inheritDoc}
 1053  
      */
 1054  
     @Override
 1055  
     public boolean equals( Object that ) {
 1056  1937
         return ReadOnlySequences.areSequencesEqual( this, that );
 1057  
     }
 1058  
 
 1059  
     /**
 1060  
      * {@inheritDoc}
 1061  
      */
 1062  
     @Override
 1063  
     public int hashCode() {
 1064  90
         return ReadOnlySequences.hashCode( this );
 1065  
     }
 1066  
 
 1067  
     /**
 1068  
      * {@inheritDoc}
 1069  
      */
 1070  
     @Override
 1071  
     public String toString() {
 1072  5
         return ReadOnlySequences.toString( this );
 1073  
     }
 1074  
 
 1075  
     /**
 1076  
      * {@inheritDoc}
 1077  
      */
 1078  
     @Override
 1079  
     protected <T> Set<T> newEmptySet() {
 1080  12
         return Set.emptySet();
 1081  
     }
 1082  
 
 1083  
     /**
 1084  
      * {@inheritDoc}
 1085  
      */
 1086  
     @Override
 1087  
     protected OrderedCollection<E> newEmptyExtensibleCollection() {
 1088  50
         return newEmptyExtensibleResultCollection();
 1089  
     }
 1090  
 
 1091  
     /**
 1092  
      * {@inheritDoc}
 1093  
      */
 1094  
     @Override
 1095  
     protected <R> OrderedCollection<R> newEmptyExtensibleResultCollection() {
 1096  63
         return emptyOrderedCollection();
 1097  
     }
 1098  
 
 1099  
     private void ensureNotEmpty() {
 1100  157
         if ( isEmpty() )
 1101  8
             throw new NoSuchElementException( EMPTY_SEQUENCE );
 1102  149
     }
 1103  
 
 1104  
     private int ensureIndexOfElementIsNot( E target, int badIndex ) {
 1105  87
         int indexOfTarget = indexOf( target );
 1106  
 
 1107  87
         if ( indexOfTarget == badIndex )
 1108  38
             throw new NoSuchElementException( String.valueOf( target ) );
 1109  
 
 1110  49
         return indexOfTarget;
 1111  
     }
 1112  
 
 1113  
     private int ensureElementIsPresent( E target ) {
 1114  18
         return ensureIndexOfElementIsNot( target, -1 );
 1115  
     }
 1116  
 
 1117  
     private void ensureIndexIsValid( int index, String failureMessage ) {
 1118  31237
         checkIndexIsValidOn( this, index, failureMessage );
 1119  31181
     }
 1120  
 
 1121  
     private void resizeIfNeeded() {
 1122  17903
         resizeIfNeeded( size() );
 1123  17903
     }
 1124  
 
 1125  
     private void resizeIfNeeded( int magnitude ) {
 1126  18314
         if ( magnitude >= storage.length ) {
 1127  33
             Object[] oldStorage = storage;
 1128  33
             int newCapacity = max( DEFAULT_INITIAL_CAPACITY, magnitude * 2 );
 1129  33
             storage = new Object[ newCapacity ];
 1130  33
             arraycopy( oldStorage, 0, storage, 0, oldStorage.length );
 1131  
         }
 1132  18314
     }
 1133  
 
 1134  
     private void writeObject( ObjectOutputStream output ) throws IOException {
 1135  4
         output.defaultWriteObject();
 1136  
 
 1137  19
         for ( int i = 0; i < numberOfElements; ++i )
 1138  15
             output.writeObject( storage[ i ] );
 1139  4
     }
 1140  
 
 1141  
     private void readObject( ObjectInputStream input )
 1142  
         throws IOException, ClassNotFoundException {
 1143  
 
 1144  4
         input.defaultReadObject();
 1145  
 
 1146  4
         storage = new Object[ numberOfElements ];
 1147  
 
 1148  19
         for ( int i = 0; i < numberOfElements; ++i )
 1149  15
             storage[ i ] = input.readObject();
 1150  4
     }
 1151  
 }