View Javadoc
1   package eu.simuline.util;
2   
3   import java.util.List;
4   import java.util.Collection;
5   import java.util.ListIterator;
6   import java.util.Iterator;
7   import java.util.ArrayList;
8   
9   /**
10   * Compared to a classical list,  
11   * the first index of this list may well be positive 
12   * and negative indices are allowed as well. 
13   * <p>
14   * As a consequence, one can add elements not only at the end of this list 
15   * but also at its beginning. 
16   * For details consider {@link #add(Object)}, {@link #addFirst(Object)} 
17   * and {@link #addLast(Object)}. 
18   * Method {@link #add(int ind, Object obj)} is not supported 
19   * because inserting an element 
20   * requires either shift of subsequent elements to the right 
21   * or preceeding elements to the left. 
22   * To determine the direction of the shift 
23   * use {@link #add(int ind, Object obj, Direction dir)} instead. 
24   * Similar considerations apply to methods removing elements. 
25   * Also affected are the corresponding collections operations 
26   * like <code>addAll</code>. 
27   * <p>
28   * Methods {@link #toArray()} and {@link #toArray(Object[])} 
29   * satisfy a generalized contract 
30   * based on the additional method {@link #firstIndex()}. 
31   * <p>
32   * Essentially this two sided list wrapps a classical list. 
33   * Various constructors allow to pass that list. 
34   * This allows to determine the performance behavior. 
35   * The signatures of the constructors 
36   * generalize the constructors known 
37   * from implementations of classical <code>List</code>s. 
38   * The observant reader observes 
39   * that the generics are slightly more restrictive than for classical lists. 
40   * This is for performance reasons. 
41   * Note that the constructors do not create a copy of the wrapped list 
42   * which may cause hidden dependencies. 
43   * If full generality is needed 
44   * the user is asked to use the corresponding factory methods. 
45   * <p>
46   * Additionally methods concerning indices are provided 
47   * like {@link #firstIndex()}, {@link #minFreeIndex()} 
48   * and it is possible to shift a list using {@link #shiftRight(int)}. 
49   *
50   * @param <E>
51   *    the class of the elements of this list. 
52   *
53   * Created: Sun Aug 26 23:25:26 2007
54   *
55   * @author <a href="mailto:ernst.reissner@simuline.eu">Ernst Reissner</a>
56   * @version 1.0
57   */
58  public final class TwoSidedList<E> implements List<E> {
59  
60      /* -------------------------------------------------------------------- *
61       * inner classes.                                                       *
62       * -------------------------------------------------------------------- */
63  
64      /**
65       * Used as an argument for methods adding or removing elements 
66       * from this list 
67       * to determine in which direction this list has to shrink or grow. 
68       */
69      public enum Direction {
70  	Left2Right {
71  	    // api-docs provided by javadoc 
72  	    void checkRange(int ind, TwoSidedList<?> list) {
73  		list.checkRange("",
74  				ind,
75  				list.firstIndex(),
76  				list.minFreeIndex() + 1);
77  	    }
78  	    // api-docs provided by javadoc 
79  	    void checkAdd1(TwoSidedList<?> list) {
80  		list.checkIncMinFreeIndex();
81  	    }
82  	    void checkAddAll(int size, TwoSidedList<?> list) {
83  		list.checkMinFreeIndex(size);
84  	    }
85  	}, Right2Left {
86  	    // api-docs provided by javadoc 
87  	    void checkRange(int ind, TwoSidedList<?> list) {
88  		list.checkRange("",
89  				ind,
90  				list.firstIndex() - 1,
91  				list.minFreeIndex());
92  	    }
93  	    // api-docs provided by javadoc 
94  	    void checkAdd1(TwoSidedList<?> list) {
95  		list.decFirstIndex();
96  	    }
97  	    void checkAddAll(int size, TwoSidedList<?> list) {
98  		list.subFirstIndex(size);
99  	    }
100 	};
101 
102 	/**
103 	 * Checks whether index <code>ind</code> 
104 	 * is in the range of <code>list</code> 
105 	 * and throws an appropriate exception if not. 
106 	 *
107 	 * @param ind
108 	 *    the index to be checked. 
109 	 * @param list
110 	 *    the twosided list under consideration. 
111  	 * @throws IndexOutOfBoundsException
112 	 *    <ul>
113 	 *    <li> for <code>this == Left2Right</code>if not 
114 	 *    <code>list.firstIndex()   &lt;= ind&lt;list.minFreeIndex()+1</code>.
115 	 *    <li> for <code>this == Right2Left</code>if not 
116 	 *    <code>list.firstIndex()-1 &lt;= ind&lt;list.minFreeIndex()  </code>.
117 	 *    </ul>
118 	 *    The message is always the same: 
119 	 *    <code>
120 	 * "Index: &lt;ind&gt; Range: &lt;firstIndex&gt; 
121 	 *       - &lt;minFreeIndex()&gt; exclusively. "
122 	 *    </code>. 
123 	 * @see #add   (int, Object,     Direction)
124 	 * @see #addAll(int, Collection, Direction)
125 	 *
126 	 * <!--used by 
127 	 * add   (int, Object obj, Direction)
128 	 * addAll(int, Collection, Direction) 
129 	 * -->
130 	 */
131 	abstract void checkRange(int ind, TwoSidedList<?> list);
132 
133 	/**
134 	 * Checks in {@link TwoSidedList#add(int, Object, Direction)} 
135 	 * whether by adding elements 
136 	 * causes underrun in {@link TwoSidedList#firstIndex()} 
137 	 * or      overrun in {@link TwoSidedList#minFreeIndex()}. 
138 	 * 
139 	 * @param list
140 	 *    the twosided list under consideration. 
141 	 * @throws IllegalStateException
142 	 *    if adding an object to this list would 
143 	 *    cause underrun in {@link TwoSidedList#firstIndex()} 
144 	 *    or     overrun in {@link TwoSidedList#minFreeIndex()} 
145 	 *    depending on this direction. 
146 	 * @see TwoSidedList#decFirstIndex()
147 	 * @see TwoSidedList#checkIncMinFreeIndex() 
148 	 * <!-- used only in add(int, E, Direction)  -->
149 	 */
150 	abstract void checkAdd1(TwoSidedList<?> list);
151 
152 	/**
153 	 * Checks in {@link TwoSidedList#addAll(int, Collection, Direction)} 
154 	 * whether by adding elements 
155 	 * causes underrun in {@link TwoSidedList#firstIndex()} 
156 	 * or      overrun in {@link TwoSidedList#minFreeIndex()}. 
157 	 * 
158 	 * @param size
159 	 *    the number of elements to be added. 
160 	 * @param list
161 	 *    the twosided list under consideration. 
162 	 * @throws IllegalStateException
163 	 *    if adding <code>size</code> objects to this list would 
164 	 *    cause underrun in {@link TwoSidedList#firstIndex()} 
165 	 *    or     overrun in {@link TwoSidedList#minFreeIndex()} 
166 	 *    depending on this direction. 
167 	 */
168 	abstract void checkAddAll(int size, TwoSidedList<?> list);
169 
170     } // enum Direction 
171 
172     /* -------------------------------------------------------------------- *
173      * fields.                                                              *
174      * -------------------------------------------------------------------- */
175 
176     /**
177      * The list backed by this two-sided list. 
178      */
179     private List<E> list;
180 
181     /**
182      * The first index in this <code>TwoSidedList</code>. 
183      * Note that this integer may well be negative. 
184      * The inequality 
185      * <code>{@link #minFreeIndex()} &gt;= {@link #firstIndex}</code> 
186      * is guaranteed. 
187      * Casually, methods adding objects have to reject them 
188      * in order not to hurt this 
189      * alhough the backed list {@link #list} 
190      * would allow adding further elements. 
191      */
192     private int firstIndex;
193 
194     /* -------------------------------------------------------------------- *
195      * constructors and static factory methods.                             *
196      * -------------------------------------------------------------------- */
197 
198     /**
199      * Creates a new <code>TwoSidedList</code> 
200      * containing the elements of {@link #list} in proper sequence 
201      * with first index given by {@link #firstIndex}. 
202      * <p>
203      * Note the difference to reference implementations such as 
204      * <code>java.util.ArrayList</code> where the type of the list argument 
205      * is <code>List&lt;? extends E&gt;</code>. 
206      * We deviate from this solution for performance reason 
207      * and provide as an alternative 
208      * the factory method {@link #create(List,int)}. 
209      * <p>
210      * CAUTION: 
211      * This list backs {@link #list} and so changes to one of the list 
212      * affect the other list. 
213      *
214      * @param list 
215      *    the list wrapped by this twosided list. 
216      * @param firstIndex
217      *    the index where this list starts growing. 
218      * @throws IllegalStateException
219      *    if <code>list</code> is so long 
220      *    and <code>firstIndex</code> is so large 
221      *    that {@link #minFreeIndex()} would overrun. 
222      */
223     public TwoSidedList(List<E> list, int firstIndex) {
224 	this.list = list;
225 	this.firstIndex = firstIndex;
226 	checkMinFreeIndex(list.size());
227     }
228 
229     /**
230      * Creates a new <code>TwoSidedList</code> 
231      * containing the elements of <code>list</code> in proper sequence 
232      * with first index given by <code>firstIndex</code>. 
233      *
234      * @param list 
235      *    the list wrapped by this twosided list. 
236      *    Changes to <code>list</code> do not influence this twosided list. 
237      * @param firstIndex
238      *    the index where this list starts growing. 
239      * @throws IllegalStateException
240      *    if <code>list</code> is so long 
241      *    and <code>firstIndex</code> is so large 
242      *    that {@link #minFreeIndex()} would overrun. 
243      */
244     public static <E> TwoSidedList<E> create(List<? extends E> list, 
245 					     int firstIndex) {
246 	return new TwoSidedList<E>(new ArrayList<E>(list), firstIndex);
247     }
248 
249     /**
250      * Creates a new <code>TwoSidedList</code> 
251      * from a <code>List</code> with  <code>firstIndex == 0</code>. 
252      * This is the canonical generalization of lists 
253      * as mentioned in the documentation 
254      * of {@link #indexOf(Object)} and of {@link #lastIndexOf(Object)}. 
255      * <p>
256      * Note the difference to reference implementations such as 
257      * <code>java.util.ArrayList</code> where the type of the list argument 
258      * is <code> List&lt;? extends E&gt;</code>. 
259      * We deviate from this solution for performance reason 
260      * and provide as an alternative 
261      * the factory method {@link #create(List,int)}. 
262      * <p>
263      * CAUTION: 
264      * Changes to <code>list</code> influence this twosided list 
265      * and may cause malfunction. 
266      * Note that unlike {@link #TwoSidedList(List, int)} 
267      * this constructor cannot throw an <code>IllegalStateException</code>. 
268      *
269      * @param list 
270      *    the list wrapped by this twosided list. 
271      */
272     public TwoSidedList(List<E> list) {
273 	this(list, 0);
274     }
275 
276     /**
277      * Creates a new <code>TwoSidedList</code> 
278      * containing the elements of <code>list</code> in proper sequence. 
279      *
280      * @param list 
281      *    the list wrapped by this twosided list. 
282      *    Changes to <code>list</code> do not influence this twosided list. 
283      */
284     public static <E> TwoSidedList<E> create(List<? extends E> list) {
285 	return new TwoSidedList<E>(new ArrayList<E>(list));
286     }
287 
288     /**
289      * Copy constructor with shallow copy of the wrapped list {@link #list}. 
290      * As a consequence, modifications of the list created 
291      * may affect the original one and the other way round. 
292      * Note that unlike {@link #TwoSidedList(List, int)} 
293      * this constructor cannot throw an <code>IllegalStateException</code>. 
294      *
295      * @param other
296      *    another <code>TwoSidedList</code>. 
297      */
298     public TwoSidedList(TwoSidedList<E> other) {
299 	this(other.list, other.firstIndex);
300 
301     }
302 
303     /**
304      * Creates a new <code>TwoSidedList</code> 
305      * as a copy of <code>other</code> 
306      * copying also the wrapped list {@link #list}. 
307      * As a consequence, the list created and the original one 
308      * act independently. 
309      * Note that unlike {@link #TwoSidedList(List, int)} 
310      * this constructor cannot throw an <code>IllegalStateException</code>. 
311      *
312      * @param other
313      *    another <code>TwoSidedList</code>. 
314      */
315     public static <E> TwoSidedList<E> create(TwoSidedList<? extends E> other) {
316 	return new TwoSidedList<E>(new ArrayList<E>(other.list),
317 				   other.firstIndex);
318     }
319 
320     /**
321      * Creates a new empty <code>TwoSidedList</code> which starts growing 
322      * with index <code>firstIndex</code>. 
323      * Note that unlike {@link #TwoSidedList(List, int)} 
324      * this constructor cannot throw an <code>IllegalStateException</code>. 
325      *
326      * @param firstIndex 
327      *    the index where this list starts growing. 
328      */
329     public TwoSidedList(int firstIndex) {
330 	this(new ArrayList<E>(), firstIndex);
331     }
332 
333     /* -------------------------------------------------------------------- *
334      * methods.                                                             *
335      * -------------------------------------------------------------------- */
336 
337     /**
338      * Checks whether index <code>ind</code> is in range 
339      * and throws an appropriate exception if not. 
340      *
341      * @param ind
342      *    the index to be checked. 
343      * @throws IndexOutOfBoundsException
344      *    if not <code>firstIndex() &lt;= ind &lt; minFreeIndex()</code> 
345      *    with message 
346      *    <code>
347      * "Index: &lt;ind&gt; Range: &lt;firstIndex&gt; 
348      *       - &lt;minFreeIndex()&gt; exclusively. "
349      *    </code>. 
350      * <!-- used by 
351      * get(int), 
352      * set(int, obj), 
353      * remove(int ind, Direction) **** is this correct? 
354      * -->
355      */
356     void checkRange(int ind) {
357 	checkRange("", ind, this.firstIndex, minFreeIndex());
358     }
359 
360     /**
361      * Checks whether index <code>ind</code> is in range 
362      * and throws an appropriate exception if not. 
363      *
364      * @param ind
365      *    the index to be checked. 
366      * @param dir
367      *    the direction in which this twosided list may grow. 
368      * @throws IndexOutOfBoundsException
369      *    <ul>
370      *    <li> for <code>dir == Left2Right</code>
371      *    if not <code>firstIndex() &lt;= ind &lt; minFreeIndex()+1</code>. 
372      *    <li> for <code>dir == Right2Left</code>
373      *    if not <code>firstIndex()-1 &lt;= ind &lt; minFreeIndex()</code>. 
374      *    </ul>
375      *    The message is always the same: 
376      *    <code>
377      * "Index: &lt;ind&gt;Range:&lt;firstIndex&gt;
378      *       - &lt;minFreeIndex()&gt;exclusively. "
379      *    </code>. 
380      * @see #add(int, Object, Direction)
381      * @see #addAll(int, Collection, Direction)
382      *
383      * <!--used by 
384      * add   (int, Object obj, Direction)
385      * addAll(int, Collection, Direction) 
386      * -->
387      */
388     private void checkRange(int ind, Direction dir) {
389 	dir.checkRange(ind, this);
390     }
391 
392     /**
393      * Checks whether index <code>ind</code> is in range 
394      * and throws an appropriate exception if not. 
395      *
396      * @param fromToNothing
397      *    either <code>""</code>, <code>"from"</code> or <code>"to"</code>. 
398      *    The latter two cases are used only in {@link #subList(int,int)} 
399      *    to check the range of the start index and of the end index 
400      *    of the sublist to be created. 
401      * @param ind
402      *    the index to be checked. 
403      * @param min
404      *    the minimal value for <code>ind</code> accepted. 
405      * @param maxP
406      *    <em>one plus</em> the maximal value for <code>ind</code> accepted. 
407      * @throws IndexOutOfBoundsException
408      *    if not <code>min &gt;= ind &lt; maxP</code>. 
409      *    The message is 
410      *    <code>
411      * "Index: &lt;ind&gt; Range: &lt;firstIndex&gt; 
412      *       - &lt;minFreeIndex()&gt; exclusively. "
413      *    </code> preceeded by <code>fromToNothing</code>. 
414      *
415      * <!--used by 
416      * Direction.checkRange(int, TwoSidedList) 
417      * checkRange(int)
418      * listIterator(int)
419      * subList(int, int)
420      * -->
421      */
422     private void checkRange(String fromToNothing, 
423 			    int ind, 
424 			    int min, 
425 			    int maxP) {
426 	if (ind < min || ind >= maxP) {
427 	    throw new IndexOutOfBoundsException
428 		(fromToNothing + "Index: " + ind + 
429 		 " Range: " + this.firstIndex + 
430 		 " - " + minFreeIndex() + " exclusively. ");
431 	}
432     }
433 
434     /**
435      * Decrements {@link #firstIndex} if possible; 
436      * otherwise throws an exception. 
437      * This method is used by methods adding objects at the head of this list. 
438      * The error message is tailored to this usage. 
439      *
440      * @throws IllegalStateException
441      *    if <code>{@link #firstIndex} == Integer.MIN_VALUE</code> 
442      *    adding an element would cause index underrun. 
443      */
444     private void decFirstIndex() {
445 	if (this.firstIndex == Integer.MIN_VALUE) {
446 	    throw new IllegalStateException
447 		("Adding an object at top of this list " + 
448 		 "would cause index underrun. ");
449 	}
450 	this.firstIndex--;
451     }
452 
453     /**
454      * Increments {@link #firstIndex} if possible; 
455      * otherwise throws an exception. 
456      * This method is used by methods removing objects 
457      * from the head of this list. 
458      * The error message is tailored to this usage. 
459      *
460      * @throws IllegalStateException
461      *    if <code>{@link #firstIndex} == Integer.MAX_VALUE</code> 
462      *    removing an element would cause index overrun. 
463      */
464     private void incFirstIndex() {
465 	if (this.firstIndex == Integer.MAX_VALUE) {
466 	    throw new IllegalStateException
467 		("Removing an object at top of this list " + 
468 		 "would cause index overrun. ");
469 	}
470 	this.firstIndex++;
471     }
472 
473     /**
474      * Checks whether incrementing {@link #minFreeIndex()} 
475      * would cause overrun of {@link #minFreeIndex()}. 
476      *
477      * @throws IllegalStateException
478      *    if incrementing {@link #minFreeIndex()} 
479      *    would cause overrun of {@link #minFreeIndex()}. 
480      */
481     void checkIncMinFreeIndex() {
482 	if (minFreeIndex() == Integer.MAX_VALUE) {
483 	    throw new IllegalStateException
484 		("Adding an object at the tail of this list " + 
485 		 "would cause index overrun. ");
486 	}
487     }
488 
489     /**
490      * Subtracts <code>numAdded</code> from {@link #firstIndex} if possible; 
491      * otherwise throws an exception. 
492      * This method is used by methods adding objects at the head of this list. 
493      * The error message is tailored to this usage. 
494      *
495      * @throws IllegalStateException
496      *    if adding <code>numAdded</code> objects 
497      *    at the head of this list 
498      *    would cause underrun of {@link #firstIndex}. 
499      */
500      private void subFirstIndex(int numAdded) {
501 	if (this.firstIndex < this.firstIndex - numAdded) {
502 	    throw new IllegalStateException
503 		("Adding " + numAdded + " objects at top of this list " + 
504 		 "would cause index underrun. ");
505 	}
506 	this.firstIndex -= numAdded;
507     }
508 
509     /**
510      * Checks whether adding <code>numAdded</code> objects 
511      * to this list **** or at the tail of this list 
512      * would cause overrun of {@link #minFreeIndex()}. 
513      *
514      * @throws IllegalStateException
515      *    if adding <code>numAdded</code> objects 
516      *    to this list **** or at the tail of this list 
517      *    would cause overrun of {@link #minFreeIndex()}. 
518      */
519     void checkMinFreeIndex(int numAdded) {
520 	assert  numAdded >= 0;
521 	if (minFreeIndex() > minFreeIndex() + numAdded) {
522 	    throw new IllegalStateException
523 		("Adding " + numAdded + " objects at the tail of this list " + 
524 		 "would cause index overrun. ");
525 	}
526     }
527 
528     /**
529      * Returns {@link #firstIndex}. 
530      */
531     public int firstIndex() {
532 	return this.firstIndex;
533     }
534 
535     /**
536      * Sets {@link #firstIndex} according to the parameter. 
537      */
538     public void firstIndex(int firstIndex) {
539 	this.firstIndex = firstIndex;
540     }
541 
542     // 
543     public int minFreeIndex() {
544 	return this.list.size() + this.firstIndex;
545     }
546 
547     /**
548      * Shifts this list <code>num</code> indices to the right. 
549      *
550      * @param num 
551      *    the number of shifts to the right 
552      *    to be performed on this list. 
553      *    A negative sign signifies a shift to the left. 
554      * @return
555      *    The new first index. 
556      * @throws IllegalStateException
557      *    if shifting would cause overrun of {@link #minFreeIndex()} 
558      *    (occuring for proper shift to the right)
559      *    or underrun of {@link #firstIndex()}
560      *    (occuring for proper shift to the left). 
561      */
562     public int shiftRight(int num) {
563 	if (num > 0) {
564 	    if (minFreeIndex() > minFreeIndex() + num) {
565 		throw new IllegalStateException
566 		    ("Shifting this list by " + num + 
567 		     " would cause index overrun. ");
568 	    }
569 	} else {
570 	    assert num <= 0;
571 	    if (this.firstIndex < this.firstIndex + num) {
572 		throw new IllegalStateException
573 		    ("Shifting this list by " + num + 
574 		     " would cause index underrun. ");
575 	    }
576 	}
577 
578 	this.firstIndex += num;
579 	return this.firstIndex;
580     }
581 
582     // caution: not wrapped. 
583     public List<E> list() {
584 	return this.list;
585     }
586 
587     /* -------------------------------------------------------------------- *
588      * methods implementing List.                                           *
589      * -------------------------------------------------------------------- */
590 
591     /**
592      * Returns the number of elements in this list. 
593      * If this list 
594      * contains more than <code>Integer.MAX_VALUE</code> elements, 
595      * returns <code>Integer.MAX_VALUE</code>. 
596      * **** gives rise to malfunction. **** 
597      *
598      * @return 
599      *    an <code>int</code> value
600      */
601     public int size() {
602 	return this.list.size();
603     }
604 
605     /**
606      * Returns true if this list contains no elements. 
607      *
608      * @return 
609      *    whether this list contains no elements 
610      *    as a <code>boolean</code> value. 
611      */
612     public boolean isEmpty() {
613 	return this.list.isEmpty();
614     }
615 
616     /**
617      * Returns whether this list contains the specified element. 
618      * More formally, returns <code>true</code> 
619      * if and only if this list contains at least one element <code>obj</code> 
620      * such that <code>(o==null ? e==null : o.equals(e))</code>.     
621      *
622      * @param obj 
623      *    an <code>Object</code> value
624      * @return 
625      *    a <code>boolean</code> value
626      * @throws ClassCastException 
627      *    if the class of <code>obj</code> 
628      *    is incompatible with {@link #list}. 
629      * @throws NullPointerException 
630      *    if <code>obj == null</code> 
631      *    and {@link #list} does not permit <code>null</code> elements. 
632      */
633     public boolean contains(final Object obj) {
634 	return this.list.contains(obj);
635     }
636 
637     /**
638      * Returns the index of the first occurrence 
639      * of the specified element <code>obj</code> in this list, 
640      * or {@link #firstIndex()}-1 if this list does not contain the element. 
641      * More formally, returns the lowest index <code>i</code> 
642      * such that <code>(obj==null ? get(i)==null : obj.equals(get(i)))</code>, 
643      * or {@link #firstIndex()}-1 if there is no such index. 
644      * <p>
645      * CAUTION: 
646      * <ul>
647      * <li>
648      * This breaks **** "extends" contract for the interface List: 
649      * Test for "element <code>obj</code> not in list" 
650      * is no longer <code>this.indexOf(obj) == -1</code> but 
651      * <code>this.indexOf(obj) &lt; this.firstIndex()-1</code>. 
652      * This is an extension in that 
653      * wrapping an ordinary list in a twosided list 
654      * is by specifying <code>firstIndex() == 0</code> 
655      * (see {@link #TwoSidedList(List list)}). 
656      * <li>
657      * Note that for <code>firstIndex() == {@link Integer#MIN_VALUE}</code> 
658      * <code>firstIndex()-1 &gt; firstIndex()</code>. 
659      * </ul>
660      *
661      * @param obj 
662      *    an <code>Object</code> value
663      * @return 
664      *    <ul>
665      *    <li>
666      *    the index of the first occurrence of <code>obj</code> 
667      *    if this object is in this list. 
668      *    In this case, the return value is within the range 
669      *    <code>firstIndex()..firstFreeIndex()-1</code>. 
670      *    <li>
671      *    <code>firstIndex()-1</code> if <code>obj</code> is not in this list. 
672      *    </ul>
673      */
674     public int indexOf(final Object obj) {
675 	return this.list.indexOf(obj) + this.firstIndex;
676     }
677 
678     /**
679      * Returns the index of the last occurrence 
680      * of the specified element <code>obj</code> in this list, 
681      * or {@link #firstIndex()}-1 if this list does not contain the element. 
682      * More formally, returns the highest index <code>i</code> 
683      * such that <code>(obj==null ? get(i)==null : obj.equals(get(i)))</code>, 
684      * or {@link #firstIndex()}-1 if there is no such index. 
685      * <p>
686      * CAUTION: 
687      * <ul>
688      * <li>
689      * This breaks **** "extends" contract for the interface List: 
690      * Test for "element <code>obj</code> not in list" 
691      * is no longer <code>this.indexOf(obj) == -1</code> but 
692      * <code>this.indexOf(obj) &lt; this.firstIndex()-1</code>. 
693      * This is an extension in that 
694      * wrapping an ordinary list in a twosided list 
695      * is by specifying <code>firstIndex() == 0</code> 
696      * (see {@link #TwoSidedList(List list)}). 
697      * <li>
698      * Note that for <code>firstIndex() == {@link Integer#MIN_VALUE}</code> 
699      * <code>firstIndex()-1 &gt; firstIndex()</code>. 
700      * </ul>
701      * **** one may expect 
702      * that in case the specified object in not in the list 
703      * 1+ the highest index is returned. 
704      * this is in general not the case. 
705      *
706      * @param obj 
707      *    an <code>Object</code> value
708      * @return 
709      *    <ul>
710      *    <li>
711      *    the index of the last occurrence of <code>obj</code> 
712      *    if this object is in this list. 
713      *    In this case, the return value is within the range 
714      *    <code>firstIndex()..firstFreeIndex()-1</code>. 
715      *    <li>
716      *    <code>firstIndex()-1</code> if <code>obj</code> is not in this list. 
717      *    </ul>
718      */
719     public int lastIndexOf(final Object obj) {
720 	return this.list.lastIndexOf(obj) + this.firstIndex;
721     }
722 
723     /**
724      * Note that this generalizes the contract of the underlying interface: 
725      * Instead of <code>this.toArray[i] == this.get(i)</code> 
726      * now only <code>this.toArray[i] == this.get(i-firstIndex())</code>. 
727      * Equality includes that the left hand side throws an exception 
728      * if and only if so does te right hand side. 
729      *
730      * @return 
731      *    an <code>Object[]</code> containing all elements in proper sequence. 
732      */
733     // api-docs provided by javadoc. 
734     public Object[] toArray() {
735 	return this.list.toArray();
736     }
737 
738     /**
739      * Note that this generalizes the contract of the underlying interface: 
740      * Instead of <code>this.toArray[i] == this.get(i)</code> 
741      * now only <code>this.toArray[i] == this.get(i-firstIndex())</code>. 
742      * Equality includes that the left hand side throws an exception 
743      * if and only if so does te right hand side. 
744      *
745      * @param objArr 
746      *    an <code>Object[]</code> value
747      * @return 
748      *    an <code>Object[]</code> value
749      */
750     // api-docs provided by javadoc. 
751     public <E> E[] toArray(final E[] objArr) {
752 	return this.list.toArray(objArr);
753     }
754 
755     /**
756      * Returns the element at the specified position in this list. 
757      *
758      * @param ind 
759      *    the index of the element to return as an <code>int</code> value. 
760      * @return 
761      *    the element at the specified position in this list. 
762      * @throws IndexOutOfBoundsException
763      *    as described for {@link #checkRange(int)}
764      */
765     public E get(final int ind) {
766 	checkRange(ind);
767 	return this.list.get(ind - this.firstIndex);
768     }
769 
770     /**
771      * Replaces the element at the <code>ind</code>th position 
772      * in this list with the specified element (optional operation).
773      *
774      * @param ind 
775      *    the index of the element to replace as an <code>int</code> value. 
776      * @param obj 
777      *    the element to be stored at the specified position. 
778      * @return 
779      *    the element previously at the <code>ind</code>th position 
780      * @throws UnsupportedOperationException 
781      *    if the <code>set</code> operation is not supported 
782      *    by {@link #list}. 
783      * @throws ClassCastException 
784      *    if the class of <code>obj</code> 
785      *    prevents it from being added to {@link #list}. 
786      * @throws NullPointerException 
787      *    if <code>obj == null</code> 
788      *    and {@link #list} does not permit <code>null</code> elements. 
789      * @throws IllegalArgumentException 
790      *    if some property of <code>obj</code> 
791      *    prevents it from being added to {@link #list}. 
792      * @throws IndexOutOfBoundsException
793      *    as described for {@link #checkRange(int)}
794      */
795     public E set(final int ind, final E obj) {
796 	checkRange(ind);
797 	return this.list.set(ind - this.firstIndex, obj);
798     }
799 
800 
801     /**
802      * Not supported by this implementation. **** breaks contract 
803      *
804      * @throws UnsupportedOperationException
805      *    use {@link #addFirst} and {@link #addLast} instead. 
806      */
807     public boolean add(final E obj) {
808 	throw new UnsupportedOperationException
809 	    ("Use addFirst(Object) or addLast(E) instead. ");
810     }
811 
812     /**
813      * Adds <code>obj</code> at the beginning of this list. 
814      * The first index returned by {@link #firstIndex()} 
815      * is decremented. 
816      *
817      * @param obj 
818      *    the <code>E</code> object to be added. 
819      * @return 
820      *    <code>true</code> by specification. 
821      * @throws UnsupportedOperationException 
822      *    if the <code>add(int,E)</code> operation is not supported 
823      *    by {@link #list}. 
824      * @throws ClassCastException 
825      *    if the class of <code>obj</code> 
826      *    prevents it from being added to {@link #list}. 
827      * @throws NullPointerException 
828      *    if <code>obj == null</code> 
829      *    and {@link #list} does not permit <code>null</code> elements. 
830      * @throws IllegalArgumentException 
831      *    if some property of <code>obj</code> 
832      *    prevents it from being added to {@link #list}. 
833      * @throws IllegalStateException
834      *    if <code>{@link #firstIndex} == Integer.MIN_VALUE</code> 
835      *    adding an element would cause index underrun. 
836      */
837     public boolean addFirst(final E obj) {
838 	// may throw an IllegalStateException 
839 	decFirstIndex();
840 	this.list.add(0, obj);
841 	return true;
842     }
843 
844     /**
845      * Adds <code>obj</code> at the end of this list. 
846      * The first index returned by {@link #firstIndex()} remains unchanged. 
847      *
848      * @param obj 
849      *    the <code>E</code> object to be added. 
850      * @return 
851      *    <code>true</code> by specification. 
852      * @throws UnsupportedOperationException 
853      *    if the <code>add(E)</code> operation is not supported 
854      *    by {@link #list}. 
855      * @throws ClassCastException 
856      *    if the class of <code>obj</code> 
857      *    prevents it from being added to {@link #list}. 
858      * @throws NullPointerException 
859      *    if <code>obj == null</code> 
860      *    and {@link #list} does not permit <code>null</code> elements. 
861      * @throws IllegalArgumentException 
862      *    if some property of <code>obj</code> 
863      *    prevents it from being added to {@link #list}. 
864      * @throws IllegalStateException
865      *    if adding objects to this list 
866      *    would cause overrun of {@link #minFreeIndex()}. 
867      */
868     public boolean addLast(final E obj) {
869 	checkIncMinFreeIndex();
870 	return this.list.add(obj);
871     }
872 
873     /**
874      * Not supported by this implementation. **** breaks contract 
875      *
876      * @throws UnsupportedOperationException
877      *    use {@link #add(int,Object,Direction)} instead. 
878      */
879     public void add(final int ind, final E obj) {
880 	throw new UnsupportedOperationException
881 	    ("Use add(int,E,Direction) instead. ");
882     }
883 
884     /**
885      * Inserts <code>obj</code> at the specified position <code>ind</code> 
886      * in this list (optional operation). 
887      * Shifts the element currently at that position (if any) 
888      * and any following/preceeding elements to the direction <code>dir</code> 
889      * (increments/decrements their indices).
890      *
891      * @param ind 
892      *    the index where to insert <code>obj</code>. 
893      *    After having performed this operation, 
894      *    <code>ind</code> is the index of <code>obj</code>. 
895      * @param obj 
896      *    the <code>E</code> element to be inserted. 
897      * @param dir 
898      *    determines the direction to shift the list. 
899      *    <ul>
900      *    <li><code>Left2Right</code>: 
901      *    shifts all subsequent objects in this list 
902      *    starting with index <code>ind</code> to the right 
903      *    adding one to their indices. 
904      *    <li><code>Right2Left</code>: 
905      *    shifts all objects in this list 
906      *    to index <code>ind</code> to the left 
907      *    subtracting one from their indices. 
908      *    </ul>
909      * @throws UnsupportedOperationException 
910      *    if the <code>add</code> operation 
911      *    is not supported by {@link #list}. 
912      * @throws ClassCastException 
913      *    if the class of <code>obj</code> 
914      *    prevents it from being added to {@link #list}. 
915      * @throws NullPointerException 
916      *    if <code>obj == null</code> 
917      *    and {@link #list} does not permit <code>null</code> elements. 
918      * @throws IllegalArgumentException 
919      *    if some property of <code>obj</code> 
920      *    prevents it from being added to {@link #list}. 
921      * @throws IndexOutOfBoundsException
922      *    as described for {@link #checkRange(int,Direction)}
923      */
924     public void add(final int ind, final E obj, final Direction dir) {
925 	checkRange(ind, dir);
926 	dir.checkAdd1(this);
927 	this.list.add(ind - this.firstIndex, obj);
928     }
929 
930     /**
931      * Not supported by this implementation. **** breaks contract 
932      *
933      * @throws UnsupportedOperationException
934      *    use {@link #remove(int,Direction)} instead. 
935      */
936     public E remove(final int ind) {
937 	throw new UnsupportedOperationException
938 	    ("Use remove(int,Direction) instead. ");
939     }
940 
941     /**
942      * Removes the element at the specified position in this list 
943      * (optional operation). 
944      * Shifts any following/preceeding elements 
945      * to the direction <code>dir</code> 
946      * (decrements/increments their indices). 
947      * Returns the element that was removed from the list. 
948      *
949      * @param ind 
950      *    the index of the element to be removed 
951      *    as an <code>int</code> value. 
952      * @return 
953      *    the element previously at the specified position. 
954      * @throws UnsupportedOperationException 
955      *    if the <code>remove(int)</code> operation 
956      *    is not supported by {@link #list}. 
957      * @throws IndexOutOfBoundsException
958      *    as described for {@link #checkRange(int)}
959      */
960     public E remove(final int ind, Direction dir) {
961 	checkRange(ind);
962 	E res = this.list.remove(ind - this.firstIndex);
963 	if (dir == Direction.Right2Left) {
964 	    // Note that this may not throw any exception in this case. 
965 	    incFirstIndex();
966 	}
967 
968 	return res;
969     }
970 
971     /**
972      * Not supported by this implementation. **** breaks contract 
973      *
974      * @throws UnsupportedOperationException
975      *    use {@link #removeFirst(Object)} 
976      *    and {@link #removeLast(Object)} instead. 
977      */
978     public boolean remove(final Object obj) {
979 	throw new UnsupportedOperationException
980 	    ("Use removeFirst(E) or removeLast(E) instead. ");
981     }
982 
983     /**
984      * Removes the first occurrence of <code>obj</code> from this list, 
985      * if present (optional operation). 
986      * If this list does not contain <code>obj</code>, it is unchanged. 
987      * More formally, removes the element with the lowest index <code>i</code> 
988      * such that <code>(obj==null ? get(i)==null : obj.equals(get(i)))</code> 
989      * (if such an element exists). 
990      * Returns <code>true</code> if this list contained the specified element 
991      * (or equivalently, if this list changed as a result of the call). 
992      * The first index returned by {@link #firstIndex()} remains unchanged. 
993      *
994      * @param obj
995      *    the element to be removed from this list, if present. 
996      * @return
997      *    whether this list contained the specified element
998      * @throws UnsupportedOperationException 
999      *    if the <code>remove(Object)</code> operation is not supported 
1000      *    by {@link #list}. 
1001      */
1002     public boolean removeFirst(final Object obj) {
1003 	return this.list.remove(obj);
1004     }
1005 
1006     /**
1007      * Removes the last occurrence of <code>obj</code> from this list, 
1008      * if present (optional operation). 
1009      * If this list does not contain <code>obj</code>, it is unchanged. 
1010      * More formally, 
1011      * removes the element with the highest index <code>i</code> 
1012      * such that <code>(obj==null ? get(i)==null : obj.equals(get(i)))</code> 
1013      * (if such an element exists). 
1014      * Returns <code>true</code> if this list contained the specified element 
1015      * (or equivalently, if this list changed as a result of the call). 
1016      * The first index returned by {@link #firstIndex()} is incremented 
1017      * if really an object was removed. 
1018      *
1019      * @param obj
1020      *    the element to be removed from this list, if present. 
1021      * @return
1022      *    whether this list contained the specified element
1023      * @throws UnsupportedOperationException 
1024      *    if the <code>remove(int)</code> **** not remove(Object) 
1025      *    operation is not supported 
1026      *    by {@link #list}. 
1027      */
1028     public boolean removeLast(final Object obj) {
1029 	int ind = this.list.lastIndexOf(obj);
1030 	if (ind == -1) {
1031 	    // obj \notin this 
1032 	    return false;
1033 	} else {
1034 	    // obj \in this 
1035 	    // Note that this may not throw any exception in this case. 
1036 	    incFirstIndex();
1037 	    this.list.remove(ind);
1038 	    return true;
1039 	}
1040     }
1041 
1042     /**
1043      * Removes all of the elements from this list (optional operation). 
1044      * The list will be empty after this call returns 
1045      * and {@link #firstIndex} is unmodified. 
1046      *
1047      * @throws UnsupportedOperationException 
1048      *    if the clear operation is not supported by {@link #list}. 
1049      */
1050     public void clear() {
1051 	this.list.clear();
1052     }
1053 
1054     /**
1055      * Not supported by this implementation. 
1056      *
1057      * @throws UnsupportedOperationException
1058      *    use {@link #addAllFirst} and {@link #addAllLast} instead. 
1059      */
1060     public boolean addAll(final Collection<? extends E> coll) {
1061 	throw new UnsupportedOperationException
1062 	    ("Use addAllFirst or addAllLast instead. ");
1063     }
1064 
1065     /**
1066      * Adds <code>obj</code> at the beginning of this list. 
1067      * in the order that they are returned 
1068      * by <code>coll</code>'s iterator (optional operation). 
1069      * The behavior of this operation is undefined 
1070      * if the specified collection is modified 
1071      * while the operation is in progress. 
1072      * (Note that this will occur if <code>coll</code> is this list, 
1073      * and it's nonempty.)
1074      * The first index returned by {@link #firstIndex()} 
1075      * is reduced by <code>coll</code>'s size. 
1076      *
1077      * @param coll 
1078      *    a <code>Collection</code> value
1079      * @return 
1080      *    whether this list changed as a result of the call 
1081      *    as a <code>boolean</code> value. 
1082      * @throws    UnsupportedOperationException 
1083      *    if the addAll operation is not supported by this {@link #list}.  
1084      * @throws    ClassCastException 
1085      *    if the class of an element of the specified collection 
1086      *    prevents it from being added to {@link #list}. 
1087      * @throws    NullPointerException 
1088      *    if the specified collection contains 
1089      *    one or more <code>null</code> elements 
1090      *    and {@link #list} does not permit <code>null</code> elements 
1091      *    or if the specified collection is <code>null</code> 
1092      * @throws    IllegalArgumentException 
1093      *    if some property of an element of the specified collection 
1094      *    prevents it from being added to {@link #list}. 
1095      * @throws IllegalStateException
1096      *    if adding <code>numAdded</code> objects 
1097      *    at the head of this list 
1098      *    would cause underrun of {@link #firstIndex}. 
1099      */
1100     public boolean addAllFirst(final Collection<? extends E> coll) {
1101 	subFirstIndex(coll.size());
1102 	return this.list.addAll(0, coll);
1103     }
1104 
1105     /**
1106      * Appends all of the elements in <code>coll</code> 
1107      * to the end of this list, 
1108      * in the order that they are returned 
1109      * by <code>coll</code>'s iterator (optional operation). 
1110      * The behavior of this operation is undefined 
1111      * if the specified collection is modified 
1112      * while the operation is in progress. 
1113      * (Note that this will occur if <code>coll</code> is this list, 
1114      * and it's nonempty.)
1115      * The first index returned by {@link #firstIndex()} remains unchanged. 
1116      *
1117      * @param coll 
1118      *    another <code>Collection</code>. 
1119      * @return 
1120      *    whether this list changed as a result of the call 
1121      *    as a <code>boolean</code> value. 
1122      * @throws     UnsupportedOperationException 
1123      *    if the addAll operation is not supported by this {@link #list}.  
1124      * @throws    ClassCastException 
1125      *    if the class of an element of the specified collection 
1126      *    prevents it from being added to {@link #list}. 
1127      * @throws    NullPointerException 
1128      *    if the specified collection contains 
1129      *    one or more <code>null</code> elements 
1130      *    and {@link #list} does not permit <code>null</code> elements 
1131      *    or if the specified collection is <code>null</code> 
1132      * @throws    IllegalArgumentException 
1133      *    if some property of an element of the specified collection 
1134      *    prevents it from being added to {@link #list}. 
1135      * @throws IllegalStateException
1136      *    if adding <code>numAdded</code> objects 
1137      *    to this list **** or at the tail of this list 
1138      *    would cause overrun of {@link #minFreeIndex()}. 
1139      */
1140     public boolean addAllLast(final Collection<? extends E> coll) {
1141 	checkMinFreeIndex(coll.size());
1142 	return this.list.addAll(coll);
1143     }
1144 
1145     /**
1146      * Not supported by this implementation. 
1147      *
1148      * @throws UnsupportedOperationException
1149      *    use {@link #addAll(int,Collection,Direction)} instead. 
1150      */
1151     public boolean addAll(final int ind, 
1152 			  final Collection<? extends E> coll) {
1153 	throw new UnsupportedOperationException
1154 	    ("Use addAll(int,Collection,Direction) instead. ");
1155     }
1156 
1157     /**
1158      * Inserts all of the elements in <code>coll</code> into this list 
1159      * at the specified position (optional operation). 
1160      * Shifts the elements currently at that positions (if any) 
1161      * and any following/preceeding elements to the direction <code>dir</code> 
1162      * (increasing/decreasing their indices by <code>coll</code>'s size). 
1163      * The new elements will appear in this list in the order 
1164      * that they are returned by the specified collection's iterator. 
1165      * The behavior of this operation is undefined 
1166      * if the specified collection is modified 
1167      * while the operation is in progress. 
1168      * (Note that this will occur if the specified collection is this list, 
1169      * and it's nonempty.)
1170      *
1171      * @param ind 
1172      *    index at which to insert the first element from <code>coll</code> 
1173      *    as an <code>int</code> value. 
1174      *    CAUTION: Note that <code>ind</code> 
1175      *    always references the first element in <code>coll</code> 
1176      *    independent from <code>dir</code>. 
1177      * @param coll 
1178      *    a <code>Collection</code> 
1179      *    containing elements to be added to this list. 
1180      * @param dir 
1181      *    determines the direction to shift the list. 
1182      *    <ul>
1183      *    <li><code>Left2Right</code>: 
1184      *    shifts all subsequent objects in this list 
1185      *    starting with index <code>ind</code> to the right 
1186      *    adding one to their indices. 
1187      *    <li><code>Right2Left</code>: 
1188      *    shifts all objects in this list 
1189      *    to index <code>ind</code> to the left 
1190      *    subtracting one from their indices. 
1191      *    </ul>
1192      * @return 
1193      *    whether this list changed as a result of the call 
1194      *    as a <code>boolean</code> value. 
1195      * @throws UnsupportedOperationException 
1196      *    if the <code>addAll</code> operation 
1197      *    is not supported by this {@link #list}.  
1198      * @throws ClassCastException 
1199      *    if the class of an element of <code>coll</code> 
1200      *    prevents it from being added to {@link #list}. 
1201      * @throws NullPointerException 
1202      *    if the <code>coll</code> contains 
1203      *    at least one <code>null</code> element 
1204      *    and {@link #list} does not permit <code>null</code> elements 
1205      *    or if <code>coll == null</code>. 
1206      * @throws IllegalArgumentException 
1207      *    if some property of an element of the specified collection 
1208      *    prevents it from being added to {@link #list}. 
1209      * @throws IndexOutOfBoundsException
1210      *    as described for {@link #checkRange(int,Direction)}
1211      * @throws IllegalStateException
1212      *    if adding <code>coll</code> to this list 
1213      *    would cause underrun of {@link #firstIndex} 
1214      *    or overrun of {@link #minFreeIndex}. 
1215      */
1216     public boolean addAll(final int ind, 
1217 			  final Collection<? extends E> coll, 
1218 			  final Direction dir) {
1219 	checkRange(ind, dir);
1220 	dir.checkAddAll(coll.size(), this);
1221 	return this.list.addAll(ind - this.firstIndex, coll);
1222     }
1223 
1224     /*
1225      * Returns an iterator over the elements in this list in proper sequence.
1226      *
1227      * @return 
1228      *    an iterator over the elements in this list in proper sequence. 
1229      */
1230     // api-docs provided by javadoc. 
1231     public Iterator<E> iterator() {
1232 	return this.list.iterator();
1233     }
1234 
1235     /*
1236      * Returns a list iterator over the elements in this list 
1237      * (in proper sequence). 
1238      *
1239      * @return 
1240      *    a <code>ListIterator</code> 
1241      */
1242     // api-docs provided by javadoc 
1243     public ListIterator<E> listIterator() {
1244 	return this.list.listIterator();
1245     }
1246 
1247     /**
1248      * ****maybe to be endowed with a direction. 
1249      *
1250      * @param ind 
1251      *    an <code>int</code> value
1252      * @return 
1253      *    a <code>ListIterator</code> value
1254      * @throws IndexOutOfBoundsException
1255      *    if not <code>firstIndex() &lt;= ind &lt;= minFreeIndex()</code> 
1256      *    with message 
1257      *    <code>
1258      * "Index: &lt;ind&gt; Range: &lt;firstIndex&gt; - 
1259      * &lt;minFreeIndex()&gt; exclusively. "
1260      *    </code>. 
1261      */
1262     public ListIterator<E> listIterator(final int ind) {
1263 	checkRange("", ind, this.firstIndex, minFreeIndex() + 1);
1264 	return this.list.listIterator(ind - this.firstIndex);
1265     }
1266 
1267     /**
1268      * Replaces the element at the <code>ind</code>th position 
1269      * in this list with the specified element (optional operation).
1270      *
1271      * @param coll 
1272      *    a <code>Collection</code> value
1273      * @return 
1274      *    a <code>boolean</code> value
1275      * @throws ClassCastException 
1276      *    if the class of one or more elements of <code>coll</code> 
1277      *    is incompatible with {@link #list}. 
1278      * @throws NullPointerException 
1279      *    if <code>coll</code> contains at least one <code>null</code> element 
1280      *    and {@link #list} is incompatible with <code>null</code> elements 
1281      *    or if <code>coll == null</code>. 
1282      */
1283     public boolean containsAll(final Collection<?> coll) {
1284 	return this.list.containsAll(coll);
1285     }
1286 
1287     /**
1288      * Not supported by this implementation. 
1289      *
1290      * @throws UnsupportedOperationException
1291      *    use {@link #removeAll(Collection,Direction)} instead. 
1292      */
1293     public boolean removeAll(final Collection<?> coll) {
1294 	throw new UnsupportedOperationException
1295 	    ("Use removeAll(Collection,Direction) instead. ");
1296     }
1297 
1298     /**
1299      * Removes from this list all of its elements 
1300      * that are contained in <code>coll</code> (optional operation). 
1301      * Shifts the elements currently at that position (if any) 
1302      * and any following/preceeding elements to the direction <code>dir</code> 
1303      * (decreasing/increasing  their indices 
1304      * by the number of elements removed). 
1305      *
1306      * @param coll 
1307      *    a <code>Collection</code> 
1308      *    containing elements to be removed from this list. 
1309      * @param dir 
1310      *    determines the direction to shift the list. 
1311      *    <ul>
1312      *    <li><code>Left2Right</code>: 
1313      *    to close gaps by removing elements 
1314      *    shifts all objects preceeding gaps to the right 
1315      *    adding one to their indices. 
1316      *    <li><code>Right2Left</code>: 
1317      *    to close gaps by removing elements 
1318      *    shifts all objects following gaps to the left  
1319      *    subtracting one from their indices. 
1320      *    </ul>
1321      * @return 
1322      *    whether this list changed as a result of the call 
1323      *    as a <code>boolean</code> value. 
1324      * @throws UnsupportedOperationException 
1325      *    if the <code>removeAll</code> operation 
1326      *    is not supported by this {@link #list}.  
1327      * @throws ClassCastException 
1328      *    if the class of an element of <code>coll</code> 
1329      *    is incompatible with {@link #list}. 
1330      * @throws NullPointerException 
1331      *    if the <code>coll</code> contains 
1332      *    at least one <code>null</code> element 
1333      *    and {@link #list} does not permit <code>null</code> elements 
1334      *    or if <code>coll == null</code>. 
1335      */
1336     public boolean removeAll(final Collection<?> coll, Direction dir) {
1337 	switch (dir) {
1338 	    case Left2Right:
1339 		return this.list.removeAll(coll);
1340 	    case Right2Left:
1341 		int oldSize = this.list.size();
1342 		boolean ret = this.list.removeAll(coll);
1343 		// This retains the inequality 
1344 		// firstIndex() <= firstFreeIndex() 
1345 		this.firstIndex += oldSize - this.list.size();
1346 		return ret;
1347 	    default:
1348 		throw new IllegalStateException();
1349 	}
1350     }
1351 
1352     /**
1353      * Not supported by this implementation. 
1354      *
1355      * @throws UnsupportedOperationException
1356      *    use {@link #retainAll(Collection,Direction)} instead. 
1357      */
1358     public boolean retainAll(final Collection<?> coll) {
1359 	throw new UnsupportedOperationException
1360 	    ("Use retainAll(Collection,Direction) instead. ");
1361     }
1362 
1363     /**
1364      * Retains only the elements in this list 
1365      * that are contained in <code>coll</code> (optional operation). 
1366      * In other words, removes from this list all the elements 
1367      * that are not contained in <code>coll</code>. 
1368      * Shifts the elements currently at that position (if any) 
1369      * and any following/preceeding elements to the direction <code>dir</code> 
1370      * (decreasing/increasing  their indices 
1371      * by the number of elements removed). 
1372      *
1373      * @param coll 
1374      *    a <code>Collection</code> 
1375      *    containing elements to be retained in this list. 
1376      * @param dir 
1377      *    determines the direction to shift the list. 
1378      *    <ul>
1379      *    <li><code>Left2Right</code>: 
1380      *    to close gaps by removing elements 
1381      *    shifts all objects preceeding gaps to the right 
1382      *    adding one to their indices. 
1383      *    <li><code>Right2Left</code>: 
1384      *    to close gaps by removing elements 
1385      *    shifts all objects following gaps to the left  
1386      *    subtracting one from their indices. 
1387      *    </ul>
1388      * @return 
1389      *    whether this list changed as a result of the call 
1390      *    as a <code>boolean</code> value. 
1391      * @throws UnsupportedOperationException 
1392      *    if the <code>retainAll</code> operation 
1393      *    is not supported by this {@link #list}.  
1394      * @throws ClassCastException 
1395      *    if the class of an element of <code>coll</code> 
1396      *    is incompatible with {@link #list}. 
1397      * @throws NullPointerException 
1398      *    if the <code>coll</code> contains 
1399      *    at least one <code>null</code> element 
1400      *    and {@link #list} does not permit <code>null</code> elements 
1401      *    or if <code>coll == null</code>. 
1402      */
1403     public boolean retainAll(final Collection<?> coll, Direction dir) {
1404 	switch (dir) {
1405 	    case Left2Right:
1406 		return this.list.retainAll(coll);
1407 	    case Right2Left:
1408 		int oldSize = this.list.size();
1409 		boolean ret = this.list.retainAll(coll);
1410 		// This retains the inequality 
1411 		// firstIndex() <= firstFreeIndex() 
1412 		this.firstIndex += oldSize - this.list.size();
1413 		return ret;
1414 	    default:
1415 		throw new IllegalStateException();
1416 	}
1417     }
1418 
1419     /**
1420      * Returns a view of the portion of this twosided list as a list 
1421      * between the specified <code>fromIndex</code>, inclusive, 
1422      * and <code>toIndex</code>, exclusive. 
1423      *
1424      * @param indStart 
1425      *    low endpoint (inclusive) of the subList to be returned. 
1426      * @param indEnd 
1427      *    high endpoint (exclusive) of the subList to be returned. 
1428      * @return 
1429      *    view of the specified range within this list. 
1430      *    The returned list is backed by this list, 
1431      *    so non-structural changes in the returned list 
1432      *    are reflected in this list, and vice-versa. 
1433      * @throws IndexOutOfBoundsException
1434      *    if not 
1435      *    <code>firstIndex() &lt;= indStart &lt;= indEnd &lt;= minFreeIndex()</code>
1436      */
1437     public List<E> subList(final int indStart, final int indEnd) {
1438 	if (indStart > indEnd) {
1439 	    throw new IndexOutOfBoundsException
1440 		("fromIndex(" + indStart + ") > toIndex(" + indEnd + ")");
1441 	}
1442 	// only one invocation can throw an exception. 
1443 	checkRange("from", indStart, this.firstIndex, minFreeIndex() + 1);
1444 	checkRange("to",   indEnd,   this.firstIndex, minFreeIndex() + 1);
1445 	return this.list.subList(indStart - this.firstIndex, 
1446 				 indEnd   - this.firstIndex);
1447     }
1448 
1449     /**
1450      * Returns a view of the portion of this twosided list 
1451      * between the specified <code>fromIndex</code>, inclusive, 
1452      * and <code>toIndex</code>, exclusive. 
1453      *
1454      * @param indStart 
1455      *    low endpoint (inclusive) of the subList to be returned. 
1456      * @param indEnd 
1457      *    high endpoint (exclusive) of the subList to be returned. 
1458      * @return 
1459      *    view of the specified range within this list. 
1460      *    The returned list is backed by this list, 
1461      *    so non-structural changes in the returned list 
1462      *    are reflected in this list, and vice-versa. 
1463      * @throws IndexOutOfBoundsException
1464      *    see {@link #subList(int,int)} 
1465      */
1466     public TwoSidedList<E> subList2(final int indStart, 
1467 				    final int indEnd) {
1468 	return new TwoSidedList<E>(subList(indStart, indEnd), indStart);
1469     }
1470 
1471     /**
1472      * The given object equals this twosided list 
1473      * if and only if it is as well a <code>TwoSidedList</code>, 
1474      * the two lists wrapped {@link #list} coincide 
1475      * and either as well the first indices {@link #firstIndex} coincide. 
1476      * CAUTION: 
1477      * Note that two empty lists with different first index are not equal. 
1478      * This is justified by the fact, 
1479      * that these two become different when the same first element is added 
1480      * to both lists. 
1481      *
1482      * @param obj 
1483      *    an <code>Object</code> value
1484      * @return 
1485      *    a <code>boolean</code> value
1486      */
1487     public boolean equals(final Object obj) {
1488 	if (!(obj instanceof TwoSidedList)) {
1489 	    return false;
1490 	}
1491 	TwoSidedList<?> other = (TwoSidedList<?>) obj;
1492 
1493 	return this.list.equals(other.list) 
1494 	    && this.firstIndex == other.firstIndex;
1495     }
1496 
1497     /**
1498      * Returns a hash code which conforms with {@link #equals(Object)}. 
1499      *
1500      * @return 
1501      *    the hash code as an <code>int</code> value. 
1502      */
1503     public int hashCode() {
1504 	return this.list.hashCode() + this.firstIndex;
1505     }
1506 
1507     // api-docs provided by javadoc 
1508     public String toString() {
1509 	StringBuilder res = new StringBuilder();
1510 	res.append("<TwoSidedList firstIndex=\"");
1511 	res.append(this.firstIndex);
1512 	res.append("\">");
1513 	res.append(this.list);
1514 	res.append("</TwoSidedList>");
1515 	return res.toString();
1516     }
1517 
1518     public static void main(String[] args) {
1519     }
1520 }