1/*
2 * Copyright (C) 2009 The Guava Authors
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
17package com.google.common.collect;
18
19import static com.google.common.base.Preconditions.checkPositionIndex;
20
21import com.google.common.annotations.GwtCompatible;
22
23import java.util.ListIterator;
24import java.util.NoSuchElementException;
25
26/**
27 * This class provides a skeletal implementation of the {@link ListIterator}
28 * interface across a fixed number of elements that may be retrieved by
29 * position. It does not support {@link #remove}, {@link #set}, or {@link #add}.
30 *
31 * @author Jared Levy
32 */
33@GwtCompatible
34abstract class AbstractIndexedListIterator<E>
35    extends UnmodifiableListIterator<E> {
36  private final int size;
37  private int position;
38
39  /**
40   * Returns the element with the specified index. This method is called by
41   * {@link #next()}.
42   */
43  protected abstract E get(int index);
44
45  /**
46   * Constructs an iterator across a sequence of the given size whose initial
47   * position is 0. That is, the first call to {@link #next()} will return the
48   * first element (or throw {@link NoSuchElementException} if {@code size} is
49   * zero).
50   *
51   * @throws IllegalArgumentException if {@code size} is negative
52   */
53  protected AbstractIndexedListIterator(int size) {
54    this(size, 0);
55  }
56
57  /**
58   * Constructs an iterator across a sequence of the given size with the given
59   * initial position. That is, the first call to {@link #nextIndex()} will
60   * return {@code position}, and the first call to {@link #next()} will return
61   * the element at that index, if available. Calls to {@link #previous()} can
62   * retrieve the preceding {@code position} elements.
63   *
64   * @throws IndexOutOfBoundsException if {@code position} is negative or is
65   *         greater than {@code size}
66   * @throws IllegalArgumentException if {@code size} is negative
67   */
68  protected AbstractIndexedListIterator(int size, int position) {
69    checkPositionIndex(position, size);
70    this.size = size;
71    this.position = position;
72  }
73
74  @Override
75  public final boolean hasNext() {
76    return position < size;
77  }
78
79  @Override
80  public final E next() {
81    if (!hasNext()) {
82      throw new NoSuchElementException();
83    }
84    return get(position++);
85  }
86
87  @Override
88  public final int nextIndex() {
89    return position;
90  }
91
92  @Override
93  public final boolean hasPrevious() {
94    return position > 0;
95  }
96
97  @Override
98  public final E previous() {
99    if (!hasPrevious()) {
100      throw new NoSuchElementException();
101    }
102    return get(--position);
103  }
104
105  @Override
106  public final int previousIndex() {
107    return position - 1;
108  }
109}
110