001 /*
002 * Copyright 2001-2010 Stephen Colebourne
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.joda.primitives.list.impl;
017
018 import java.util.Collection;
019 import java.util.ConcurrentModificationException;
020 import java.util.Iterator;
021 import java.util.List;
022 import java.util.NoSuchElementException;
023
024 import org.joda.primitives.CharUtils;
025 import org.joda.primitives.collection.impl.AbstractCharCollection;
026 import org.joda.primitives.iterator.CharIterator;
027 import org.joda.primitives.list.CharList;
028 import org.joda.primitives.listiterator.CharListIterator;
029
030 /**
031 * Abstract base class for lists of primitive <code>char</code> elements.
032 * <p>
033 * This class implements {@link java.util.Collection Collection} allowing
034 * seamless integration with other APIs.
035 * <p>
036 * The <code>get(int)</code> and <code>size()</code> methods must be
037 * implemented by subclases.
038 * To make the subclass modifiable, the <code>add(int, char)</code>,
039 * <code>removeIndex(int)</code> and set(int, char) must also be implemented.
040 * Subclasses may override other methods to increase efficiency.
041 *
042 * @author Stephen Colebourne
043 * @author Rodney Waldhoff
044 * @author Jason Tiscione
045 * @version CODE GENERATED
046 * @since 1.0
047 */
048 public abstract class AbstractCharList extends AbstractCharCollection implements CharList {
049 // This file is CODE GENERATED. Do not change manually.
050
051 /**
052 * Constructor.
053 */
054 protected AbstractCharList() {
055 super();
056 }
057
058 // CharList methods
059 //-----------------------------------------------------------------------
060 /**
061 * Gets an iterator over this list.
062 *
063 * @return an iterator over this list, not null
064 */
065 public CharListIterator iterator() {
066 return listIterator(0);
067 }
068
069 /**
070 * Gets a list iterator over this list.
071 * <p>
072 * This implementation uses <code>charListIterator(int)</code>.
073 *
074 * @return an iterator over this list, not null
075 */
076 public CharListIterator listIterator() {
077 return listIterator(0);
078 }
079
080 /**
081 * Gets a list iterator over this list from a start index.
082 *
083 * @param index the index to start from
084 * @return an iterator over this list, not null
085 * @throws IndexOutOfBoundsException if the index is invalid
086 */
087 public CharListIterator listIterator(int index) {
088 checkIndex(index);
089 return new PListIterator(this, index);
090 }
091
092 /**
093 * Gets the first primitive value.
094 *
095 * @return value at index zero
096 * @throws IndexOutOfBoundsException if the size is zero
097 */
098 public char firstChar() {
099 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