View Javadoc

1   /*
2    *  Copyright 2001-2010 Stephen Colebourne
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  package org.joda.primitives.list.impl;
17  
18  import java.util.Collection;
19  import java.util.ConcurrentModificationException;
20  import java.util.Iterator;
21  import java.util.List;
22  import java.util.NoSuchElementException;
23  
24  import org.joda.primitives.CharUtils;
25  import org.joda.primitives.collection.impl.AbstractCharCollection;
26  import org.joda.primitives.iterator.CharIterator;
27  import org.joda.primitives.list.CharList;
28  import org.joda.primitives.listiterator.CharListIterator;
29  
30  /**
31   * Abstract base class for lists of primitive <code>char</code> elements.
32   * <p>
33   * This class implements {@link java.util.Collection Collection} allowing
34   * seamless integration with other APIs.
35   * <p>
36   * The <code>get(int)</code> and <code>size()</code> methods must be
37   * implemented by subclases.
38   * To make the subclass modifiable, the <code>add(int, char)</code>,
39   * <code>removeIndex(int)</code> and set(int, char) must also be implemented.
40   * Subclasses may override other methods to increase efficiency.
41   *
42   * @author Stephen Colebourne
43   * @author Rodney Waldhoff
44   * @author Jason Tiscione
45   * @version CODE GENERATED
46   * @since 1.0
47   */
48  public abstract class AbstractCharList extends AbstractCharCollection implements CharList {
49      // This file is CODE GENERATED. Do not change manually.
50  
51      /**
52       * Constructor.
53       */
54      protected AbstractCharList() {
55          super();
56      }
57  
58      // CharList methods
59      //-----------------------------------------------------------------------
60      /**
61       * Gets an iterator over this list.
62       *
63       * @return an iterator over this list, not null
64       */
65      public CharListIterator iterator() {
66          return listIterator(0);
67      }
68  
69      /**
70       * Gets a list iterator over this list.
71       * <p>
72       * This implementation uses <code>charListIterator(int)</code>.
73       *
74       * @return an iterator over this list, not null
75       */
76      public CharListIterator listIterator() {
77          return listIterator(0);
78      }
79  
80      /**
81       * Gets a list iterator over this list from a start index.
82       *
83       * @param index  the index to start from
84       * @return an iterator over this list, not null
85       * @throws IndexOutOfBoundsException if the index is invalid
86       */
87      public CharListIterator listIterator(int index) {
88          checkIndex(index);
89          return new PListIterator(this, index);
90      }
91  
92      /**
93       * Gets the first primitive value.
94       *
95       * @return value at index zero
96       * @throws IndexOutOfBoundsException if the size is zero
97       */
98      public char firstChar() {
99          return getChar(0);
100     }
101 
102     /**
103      * Gets the last primitive value.
104      *
105      * @return value at index <code>size() - 1</code>
106      * @throws IndexOutOfBoundsException if the size is zero
107      */
108     public char lastChar() {
109         return getChar(size() - 1);
110     }
111 
112     /**
113      * Checks whether this collection contains a specified primitive value.
114      * <p>
115      * This implementation uses <code>getChar(int)</code>.
116      *
117      * @param value  the value to search for
118      * @return <code>true</code> if the value is found
119      */
120     public boolean contains(char value) {
121         for (int i = 0, isize = size(); i < isize; i++) {
122             if (getChar(i) == value) {
123                 return true;
124             }
125         }
126         return false;
127     }
128 
129     /**
130      * Gets the first index of the specified primitive value.
131      * <p>
132      * This implementation uses <code>indexof(char, int)</code>.
133      *
134      * @param value  the value to search for
135      * @return the zero-based index, or <code>-1</code> if not found
136      */
137     public int indexOf(char value) {
138         return indexOf(value, 0);
139     }
140 
141     /**
142      * Gets the first index of the specified primitive value from an index.
143      * <p>
144      * This method follows the conventions of <code>String</code> in that a
145      * negative index is treated as zero, and an index greater than the list
146      * size will simply return <code>-1</code>.
147      * <p>
148      * This implementation uses <code>get(int)</code>.
149      *
150      * @param value  the value to search for
151      * @param fromIndexInclusive  the index to start searching from, inclusive
152      * @return the zero-based index, or <code>-1</code> if not found
153      */
154     public int indexOf(char value, int fromIndexInclusive) {
155         if (fromIndexInclusive < 0) {
156             fromIndexInclusive = 0;
157         }
158         for (int i = fromIndexInclusive, isize = size(); i < isize; i++) {
159             if (getChar(i) == value) {
160                 return i;
161             }
162         }
163         return -1;
164     }
165 
166     /**
167      * Gets the last index of the specified primitive value.
168      * <p>
169      * This implementation uses <code>lastIndexof(char, int)</code>.
170      *
171      * @param value  the value to search for
172      * @return the zero-based index, or <code>-1</code> if not found
173      */
174     public int lastIndexOf(char value) {
175         return lastIndexOf(value, size());
176     }
177 
178     /**
179      * Gets the first index of the specified primitive value from an index.
180      * <p>
181      * This method follows the conventions of <code>String</code> in that an
182      * index greater than the list size will start searching at the list size,
183      * and a negative index simply returns <code>-1</code>.
184      * <p>
185      * This implementation uses <code>get(int)</code>.
186      *
187      * @param value  the value to search for
188      * @param fromIndexInclusive  the index to start searching from, inclusive
189      * @return the zero-based index, or <code>-1</code> if not found
190      */
191     public int lastIndexOf(char value, int fromIndexInclusive) {
192         if (fromIndexInclusive >= size()) {
193             fromIndexInclusive = size() - 1;
194         }
195         for (int i = fromIndexInclusive; i >= 0; i--) {
196             if (getChar(i) == value) {
197                 return i;
198             }
199         }
200         return -1;
201     }
202 
203     /**
204      * Gets the contents of the list as a String.
205      *
206      * @return the list contents
207      */
208     public String toStringContents() {
209         return new String(toCharArray());
210     }
211 
212     /**
213      * Gets a range of elements as an array.
214      *
215      * @param fromIndexInclusive  the index to start from, inclusive
216      * @param toIndexExclusive  the index to end at, exclusive
217      * @return a new array containing a copy of the range of elements, not null
218      * @throws IndexOutOfBoundsException if either index is invalid
219      */
220     public char[] toCharArray(int fromIndexInclusive, int toIndexExclusive) {
221         checkRange(fromIndexInclusive, toIndexExclusive);
222         
223         if (fromIndexInclusive == toIndexExclusive) {
224             return CharUtils.EMPTY_CHAR_ARRAY;
225         }
226         int size = toIndexExclusive - fromIndexInclusive;
227         char[] result = new char[size];
228         arrayCopy(fromIndexInclusive, result, 0, size);
229         return result;
230     }
231 
232     /**
233      * Gets a range view of part of this list.
234      * <p>
235      * This method allows operations to work on a range within the greater list.
236      * Changes made to the either object will affect the other.
237      *
238      * @param fromIndexInclusive  the index to start from, inclusive
239      * @param toIndexExclusive  the index to end at, exclusive
240      * @return a new CharList for the subList, not null
241      * @throws IndexOutOfBoundsException if either index is invalid
242      */
243     public CharList subList(int fromIndexInclusive, int toIndexExclusive) {
244         return null; // TODO
245     }
246 
247     /**
248      * Clears the listof all elements (optional operation).
249      * <p>
250      * This implementation uses <code>removeRange(int, int)</code>.
251      *
252      * @throws UnsupportedOperationException if method not supported by this collection
253      */
254     public void clear() {
255         removeRange(0, size());
256     }
257 
258     /**
259      * Adds a primitive value to this collection (optional operation).
260      * <p>
261      * This implementation uses <code>add(int, char)</code>.
262      *
263      * @param value  the value to add to this collection
264      * @return <code>true</code> if this collection was modified by this method call
265      * @throws IllegalArgumentException if value is rejected by this collection
266      * @throws UnsupportedOperationException if not supported by this collection
267      */
268     public boolean add(char value) {
269         checkAddModifiable();
270         return add(size(), value);
271     }
272 
273     /**
274      * Adds a primitive value to this list at an index (optional operation).
275      * <p>
276      * This implementation throws UnsupportedOperationException.
277      *
278      * @param index  the index to add at
279      * @param value  the value to add to this collection
280      * @return <code>true</code> if this list was modified by this method call
281      * @throws IndexOutOfBoundsException if the index is invalid
282      * @throws IllegalArgumentException if value is rejected by this collection
283      * @throws UnsupportedOperationException if not supported by this collection
284      */
285     public boolean add(int index, char value) {
286         throw new UnsupportedOperationException("List does not support add");
287     }
288 
289     /**
290      * Adds an array of primitive values to this list at an index (optional operation).
291      * <p>
292      * This implementation uses <code>addAll(int, char)</code>.
293      *
294      * @param values  the values to add to this collection, null treated as empty array
295      * @return <code>true</code> if this list was modified by this method call
296      * @throws IndexOutOfBoundsException if the index is invalid
297      * @throws IllegalArgumentException if value is rejected by this collection
298      * @throws UnsupportedOperationException if not supported by this collection
299      */
300     public boolean addAll(char[] values) {
301         checkAddModifiable();
302         return addAll(size(), values);
303     }
304 
305     /**
306      * Adds an array of primitive values to this list at an index (optional operation).
307      * <p>
308      * This method is optional, throwing an UnsupportedOperationException if the
309      * collection cannot be added to.
310      *
311      * @param index  the index to add at
312      * @param values  the values to add to this collection, null treated as empty array
313      * @return <code>true</code> if this list was modified by this method call
314      * @throws IndexOutOfBoundsException if the index is invalid
315      * @throws IllegalArgumentException if value is rejected by this collection
316      * @throws UnsupportedOperationException if not supported by this collection
317      */
318     public boolean addAll(int index, char[] values) {
319         checkAddModifiable();
320         checkIndex(index);
321         boolean changed = false;
322         if (values != null) {
323             for (int i = 0; i < values.length; i++) {
324                 changed |= add(index + i, values[i]);
325             }
326         }
327         return changed;
328     }
329 
330     /**
331      * Removes a primitive value by index from the list (optional operation).
332      * <p>
333      * This implementation throws UnsupportedOperationException.
334      *
335      * @param index  the index to remove from
336      * @return the primitive value previously at this index
337      * @throws IndexOutOfBoundsException if the index is invalid
338      * @throws UnsupportedOperationException if not supported by this collection
339      */
340     public char removeCharAt(int index) {
341         throw new UnsupportedOperationException("List does not support remove");
342     }
343 
344     /**
345      * Removes the first occurrence of a primitive value from the list (optional operation).
346      * <p>
347      * This implementation uses <code>get(int)</code> and <code>removeCharAt(int)</code>.
348      *
349      * @param value  the value to remove
350      * @return the primitive value previously at this index
351      * @throws UnsupportedOperationException if not supported by this collection
352      */
353     public boolean removeChar(char value) {
354         checkRemoveModifiable();
355         for (int i = 0, isize = size(); i < isize; i++) {
356             if (getChar(i) == value) {
357                 removeCharAt(i);
358                 return true;
359             }
360         }
361         return false;
362     }
363 
364     /**
365      * Removes a range of values from the list (optional operation).
366      * <p>
367      * This implementation uses <code>removeCharAt(int)</code>.
368      *
369      * @param fromIndexInclusive  the start of the range to remove, inclusive
370      * @param toIndexExclusive  the end of the range to remove, exclusive
371      * @return <code>true</code> if the collection was modified
372      * @throws IndexOutOfBoundsException if the index is invalid
373      * @throws UnsupportedOperationException if remove is not supported
374      */
375     public boolean removeRange(int fromIndexInclusive, int toIndexExclusive) {
376         checkRemoveModifiable();
377         checkRange(fromIndexInclusive, toIndexExclusive);
378         if (fromIndexInclusive == toIndexExclusive) {
379             return false;
380         }
381         for (int i = size() - 1; i >= 0; i--) {
382             removeCharAt(i);
383         }
384         return true;
385     }
386 
387     /**
388      * Sets the primitive value at a specified index.
389      * <p>
390      * This implementation throws UnsupportedOperationException.
391      *
392      * @param index  the index to set
393      * @param value  the value to store
394      * @return the previous value at the index
395      * @throws IndexOutOfBoundsException if the index is invalid
396      * @throws IllegalArgumentException if value is rejected by this collection
397      * @throws UnsupportedOperationException if not supported by this collection
398      */
399     public char set(int index, char value) {
400         throw new UnsupportedOperationException("List does not support set");
401     }
402 
403     // List methods
404     //-----------------------------------------------------------------------
405     /**
406      * Gets the <code>Character</code> value at the specified index.
407      *
408      * @param index  the index to get from
409      * @return value at the index
410      * @throws IndexOutOfBoundsException if the index is invalid
411      */
412     public Character get(int index) {
413         return CharUtils.toObject(getChar(index));
414     }
415 
416     /**
417      * Gets the first <code>Character</code> value.
418      *
419      * @return value at index zero or null if the size is zero
420      */
421     public Character first() {
422         if (size() == 0) {
423             return null;
424         }
425         return get(0);
426     }
427 
428     /**
429      * Gets the last <code>Character</code> value.
430      *
431      * @return value at index <code>size() - 1</code> or null if the size is zero
432      */
433     public Character last() {
434         if (size() == 0) {
435             return null;
436         }
437         return get(size() - 1);
438     }
439 
440     /**
441      * Gets the first index of the specified <code>Character</code> value.
442      *
443      * @param value  the value to search for
444      * @return the zero-based index, or <code>-1</code> if not found
445      * @throws NullPointerException if the value if null
446      * @throws ClassCastException if the object is not <code>Character</code>
447      */
448     public int indexOf(Object value) {
449         return indexOf(CharUtils.toPrimitive(value));
450     }
451 
452     /**
453      * Gets the first index of the specified <code>Character</code> value from an index.
454      * <p>
455      * This method follows the conventions of <code>String</code> in that a
456      * negative index is treated as zero, and an index greater than the list
457      * size will simply return <code>-1</code>.
458      *
459      * @param value  the value to search for
460      * @param fromIndexInclusive  the index to start searching from, inclusive
461      * @return the zero-based index, or <code>-1</code> if not found
462      * @throws NullPointerException if the value if null
463      * @throws ClassCastException if the object is not <code>Character</code>
464      */
465     public int indexOf(Object value, int fromIndexInclusive) {
466         return indexOf(CharUtils.toPrimitive(value), fromIndexInclusive);
467     }
468 
469     /**
470      * Gets the last index of the specified <code>Character</code> value.
471      *
472      * @param value  the value to search for
473      * @return the zero-based index, or <code>-1</code> if not found
474      * @throws NullPointerException if the value if null
475      * @throws ClassCastException if the object is not <code>Character</code>
476      */
477     public int lastIndexOf(Object value) {
478         return lastIndexOf(CharUtils.toPrimitive(value));
479     }
480 
481     /**
482      * Gets the first index of the specified <code>Character</code> value from an index.
483      * <p>
484      * This method follows the conventions of <code>String</code> in that an
485      * index greater than the list size will start searching at the list size,
486      * and a negative index simply returns <code>-1</code>.
487      *
488      * @param value  the value to search for
489      * @param fromIndexInclusive  the index to start searching from, inclusive
490      * @return the zero-based index, or <code>-1</code> if not found
491      * @throws NullPointerException if the value if null
492      * @throws ClassCastException if the object is not <code>Character</code>
493      */
494     public int lastIndexOf(Object value, int fromIndexInclusive) {
495         return lastIndexOf(CharUtils.toPrimitive(value), fromIndexInclusive);
496     }
497 
498     /**
499      * Adds the <code>Character</code> value to this collection (optional operation).
500      * <p>
501      * This method is optional, throwing an UnsupportedOperationException if the
502      * collection cannot be added to.
503      *
504      * @param value  the value to add to this collection
505      * @return <code>true</code> if this collection was modified by this method call
506      * @throws IllegalArgumentException if value is rejected by this collection
507      * @throws UnsupportedOperationException if not supported by this collection
508      */
509     public boolean add(Character value) {
510         checkAddModifiable();
511         return add(size(), CharUtils.toPrimitive(value));
512     }
513 
514     /**
515      * Adds the <code>Character</code> value to this list at an index (optional operation).
516      * <p>
517      * This method is optional, throwing an UnsupportedOperationException if the
518      * collection cannot be added to.
519      *
520      * @param index  the index to add at
521      * @param value  the value to add to this collection
522      * @throws IndexOutOfBoundsException if the index is invalid
523      * @throws ClassCastException if the object is not <code>Character</code>
524      * @throws IllegalArgumentException if value is rejected by this collection
525      * @throws UnsupportedOperationException if not supported by this collection
526      */
527     public void add(int index, Character value) {
528         checkAddModifiable();
529         checkIndex(index);
530         add(index, CharUtils.toPrimitive(value));
531     }
532 
533     /**
534      * Adds an array of <code>Character</code> values to this list at an index (optional operation).
535      * <p>
536      * This method is optional, throwing an UnsupportedOperationException if the
537      * collection cannot be added to.
538      *
539      * @param index  the index to add at
540      * @param coll  the values to add to this collection
541      * @return <code>true</code> if this list was modified by this method call
542      * @throws IndexOutOfBoundsException if the index is invalid
543      * @throws ClassCastException if any object is not <code>Character</code>
544      * @throws IllegalArgumentException if value is rejected by this collection
545      * @throws UnsupportedOperationException if not supported by this collection
546      */
547     public boolean addAll(int index, Collection<? extends Character> coll) {
548         checkAddModifiable();
549         checkIndex(index);
550         return addAll(index, CharUtils.toPrimitiveArray(coll));
551     }
552 
553     /**
554      * Removes a primitive value by index from the list (optional operation).
555      * <p>
556      * This implementation uses <code>removeCharAt(int)</code>.
557      *
558      * @deprecated This method should only be used when working with List and
559      *  not when working with CharList - use <code>removeCharAt(int)</code>
560      * @param index  the index to remove from
561      * @return the primitive value previously at this index
562      * @throws IndexOutOfBoundsException if the index is invalid
563      * @throws UnsupportedOperationException if not supported by this collection
564      */
565     public Character remove(int index) {
566         checkRemoveModifiable();
567         return CharUtils.toObject(removeCharAt(index));
568     }
569 
570     /**
571      * Sets the <code>Character</code> value at a specified index.
572      * <p>
573      * This implementation uses <code>set(int, char)</code>.
574      *
575      * @param index  the index to set
576      * @param value  the value to store
577      * @return the previous value at the index
578      * @throws IndexOutOfBoundsException if the index is invalid
579      * @throws IllegalArgumentException if value is rejected by this collection
580      * @throws UnsupportedOperationException if not supported by this collection
581      */
582     public Character set(int index, Character value) {
583         checkSetModifiable();
584         checkIndexExists(index);
585         return CharUtils.toObject(set(index, CharUtils.toPrimitive(value)));
586     }
587 
588     //-----------------------------------------------------------------------
589     /**
590      * Compares this list to another as per the contract of <code>List</code>.
591      *
592      * @param obj  the object to compare to
593      * @return <code>true</code> if the lists are equal
594      */
595     public boolean equals(Object obj) {
596         if (obj == this) {
597             return true;
598         }
599         if (obj instanceof CharList) {
600             CharList other = (CharList) obj;
601             if (size() != other.size()) {
602                 return false;
603             }
604             CharIterator it1 = listIterator();
605             CharIterator it2 = other.listIterator();
606             while (it1.hasNext() && it2.hasNext()) {
607                 if (it1.nextChar() != it2.nextChar()) {
608                     return false;
609                 }
610             }
611             return true;
612         } else if (obj instanceof List<?>) {
613             List<?> other = (List<?>) obj;
614             if (size() != other.size()) {
615                 return false;
616             }
617             CharIterator it1 = listIterator();
618             Iterator<?> it2 = other.listIterator();
619             while (it1.hasNext() && it2.hasNext()) {
620                 Object next = it2.next();
621                 if (isToPrimitivePossible(next) == false) {
622                     return false;
623                 }
624                 if (it1.nextChar() != toPrimitive(next)) {
625                     return false;
626                 }
627             }
628             return true;
629         } else {
630             return false;
631         }
632     }
633 
634     /**
635      * Gets the hashCode of this list as per the contract of <code>List</code>.
636      *
637      * @return the hash code for this list
638      */
639     public int hashCode() {
640         int hashCode = 1;
641         Iterator<Character> it = iterator();
642         while (it.hasNext()) {
643             Object obj = it.next();
644             hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
645         }
646         return hashCode;
647     }
648 
649     //-----------------------------------------------------------------------
650     /**
651      * Copies data from this collection into the specified array.
652      * This method is pre-validated.
653      * 
654      * @param fromIndex  the index to start from
655      * @param dest  the destination array
656      * @param destIndex  the destination start index
657      * @param size  the number of items to copy
658      */
659     protected void arrayCopy(int fromIndex, char[] dest, int destIndex, int size) {
660         for (int i = 0; i < size; i++) {
661             dest[i + destIndex] = getChar(i + fromIndex);
662         }
663     }
664 
665     /**
666      * Are the set methods supported.
667      * <p>
668      * This implementation returns false.
669      *
670      * @return true if supported
671      */
672     protected boolean isSetModifiable() {
673         return false;
674     }
675 
676     /**
677      * Is the collection modifiable in any way.
678      *
679      * @return true if supported
680      */
681     public boolean isModifiable() {
682         return isAddModifiable() || isRemoveModifiable() || isSetModifiable();
683     }
684 
685     /**
686      * Check whether add is suported and throw an exception.
687      */
688     protected void checkSetModifiable() {
689         if (isSetModifiable() == false) {
690             throw new UnsupportedOperationException("Collection does not support set");
691         }
692     }
693 
694     /**
695      * Checks whether an index is valid or not.
696      * 
697      * @param index  the index to check
698      * @throws IndexOutOfBoundsException if either index is invalid
699      */
700     protected void checkIndexExists(int index) {
701         if (index < 0) {
702             throw new ArrayIndexOutOfBoundsException(
703                 "Index less than zero: " + index + " < 0");
704         }
705         if (index >= size()) {
706             throw new ArrayIndexOutOfBoundsException(
707                 "Index greater than/equal to size(): " + index + " >= " + size());
708         }
709     }
710 
711     /**
712      * Checks whether an index is valid or not.
713      * 
714      * @param index  the index to check
715      * @throws IndexOutOfBoundsException if either index is invalid
716      */
717     protected void checkIndex(int index) {
718         if (index < 0) {
719             throw new ArrayIndexOutOfBoundsException(
720                 "Index less than zero: " + index + " < 0");
721         }
722         if (index > size()) {
723             throw new ArrayIndexOutOfBoundsException(
724                 "Index greater than size(): " + index + " > " + size());
725         }
726     }
727 
728     /**
729      * Checks whether a range is valid or not.
730      * 
731      * @param fromIndexInclusive  the index to start from, inclusive
732      * @param toIndexExclusive  the index to end at, exclusive
733      * @throws IndexOutOfBoundsException if either index is invalid
734      */
735     protected void checkRange(int fromIndexInclusive, int toIndexExclusive) {
736         if (fromIndexInclusive < 0) {
737             throw new ArrayIndexOutOfBoundsException(
738                 "From index less than zero: " + fromIndexInclusive + " < 0");
739         }
740         if (toIndexExclusive > size()) {
741             throw new ArrayIndexOutOfBoundsException(
742                 "To index greater than size(): " + toIndexExclusive + " > " + size());
743         }
744         if (fromIndexInclusive > toIndexExclusive) {
745             throw new ArrayIndexOutOfBoundsException(
746                 "To index greater than from index: " + fromIndexInclusive + " > " + toIndexExclusive);
747         }
748     }
749 
750     //-----------------------------------------------------------------------
751     /**
752      * List iterator.
753      */
754     protected static class PListIterator implements CharListIterator {
755 
756         private final AbstractCharList iList;
757         private final int iStart;
758         private int iCursor = 0;
759         private int iLastIndex = -1;
760         
761         protected PListIterator(AbstractCharList list, int start) {
762             super();
763             this.iList = list;
764             this.iStart = start;
765             this.iCursor = start;
766         }
767 
768         //-----------------------------------------------------------------------
769         public boolean hasNext() {
770             return (iCursor < iList.size());
771         }
772 
773         public char nextChar() {
774             if (hasNext() == false) {
775                 throw new NoSuchElementException("No more elements available");
776             }
777             iLastIndex = iCursor;
778             return iList.getChar(iCursor++);
779         }
780 
781         public Character next() {
782             return iList.toObject(nextChar());
783         }
784 
785         public int nextIndex() {
786             return iCursor;
787         }
788 
789         //-----------------------------------------------------------------------
790         public boolean hasPrevious() {
791             return (iCursor > 0);
792         }
793 
794         public char previousChar() {
795             if (hasPrevious() == false) {
796                 throw new NoSuchElementException("No more elements available");
797             }
798             iLastIndex = --iCursor;
799             return iList.getChar(iCursor);
800         }
801 
802         public Character previous() {
803             return iList.toObject(previousChar());
804         }
805 
806         public int previousIndex() {
807             return iCursor - 1;
808         }
809 
810         //-----------------------------------------------------------------------
811         public void remove() {
812             iList.checkRemoveModifiable();
813             if (iLastIndex == -1) {
814                 throw new IllegalStateException("Element cannot be removed");
815             }
816             iList.removeCharAt(iLastIndex);
817             iCursor = iLastIndex;
818             iLastIndex = -1;
819         }
820 
821         public void add(char value) {
822             iList.checkAddModifiable();
823             try {
824                 iList.add(iCursor++, value);
825                 iLastIndex = -1;
826             } catch (IndexOutOfBoundsException ex) {
827                 throw new ConcurrentModificationException("The underlying list was modified");
828             }
829         }
830 
831         public void add(Character obj) {
832             iList.checkAddModifiable();
833             add(iList.toPrimitive(obj));
834         }
835         
836         public void set(char value) {
837             iList.checkSetModifiable();
838             if (iLastIndex == -1) {
839                 throw new IllegalStateException("Element cannot be set");
840             }
841             try {
842                 iList.set(iLastIndex, value);
843             } catch (IndexOutOfBoundsException ex) {
844                 throw new ConcurrentModificationException("The underlying list was modified");
845             }
846         }
847 
848         public void set(Character obj) {
849             iList.checkSetModifiable();
850             set(iList.toPrimitive(obj));
851         }
852 
853         //-----------------------------------------------------------------------
854         public boolean isModifiable() {
855             return iList.isModifiable();
856         }
857 
858         public boolean isResettable() {
859             return true;
860         }
861 
862         public void reset() {
863             iCursor = iStart;
864         }
865 
866     }
867 
868 }
869