| /* |
| * Copyright 2007 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package java.util; |
| |
| import static javaemul.internal.InternalPreconditions.checkCriticalPositionIndexes; |
| import static javaemul.internal.InternalPreconditions.checkElement; |
| import static javaemul.internal.InternalPreconditions.checkElementIndex; |
| import static javaemul.internal.InternalPreconditions.checkNotNull; |
| import static javaemul.internal.InternalPreconditions.checkPositionIndex; |
| import static javaemul.internal.InternalPreconditions.checkState; |
| |
| import jsinterop.annotations.JsNonNull; |
| |
| /** |
| * Skeletal implementation of the List interface. <a |
| * href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/AbstractList.html">[Sun |
| * docs]</a> |
| * |
| * @param <E> the element type. |
| */ |
| public abstract class AbstractList<E> extends AbstractCollection<E> implements |
| List<E> { |
| |
| private class IteratorImpl implements Iterator<E> { |
| /* |
| * i is the index of the item that will be returned on the next call to |
| * next() last is the index of the item that was returned on the previous |
| * call to next() or previous (for ListIterator), -1 if no such item exists. |
| */ |
| |
| int i = 0, last = -1; |
| |
| @Override |
| public boolean hasNext() { |
| return i < AbstractList.this.size(); |
| } |
| |
| @Override |
| public E next() { |
| checkElement(hasNext()); |
| |
| return AbstractList.this.get(last = i++); |
| } |
| |
| @Override |
| public void remove() { |
| checkState(last != -1); |
| |
| AbstractList.this.remove(last); |
| i = last; |
| last = -1; |
| } |
| } |
| |
| /** |
| * Implementation of <code>ListIterator</code> for abstract lists. |
| */ |
| private final class ListIteratorImpl extends IteratorImpl implements |
| ListIterator<E> { |
| /* |
| * i is the index of the item that will be returned on the next call to |
| * next() last is the index of the item that was returned on the previous |
| * call to next() or previous (for ListIterator), -1 if no such item exists. |
| */ |
| |
| private ListIteratorImpl() { |
| // Nothing to do |
| } |
| |
| private ListIteratorImpl(int start) { |
| checkPositionIndex(start, AbstractList.this.size()); |
| |
| i = start; |
| } |
| |
| @Override |
| public void add(E o) { |
| AbstractList.this.add(i, o); |
| i++; |
| last = -1; |
| } |
| |
| @Override |
| public boolean hasPrevious() { |
| return i > 0; |
| } |
| |
| @Override |
| public int nextIndex() { |
| return i; |
| } |
| |
| @Override |
| public E previous() { |
| checkElement(hasPrevious()); |
| |
| return AbstractList.this.get(last = --i); |
| } |
| |
| @Override |
| public int previousIndex() { |
| return i - 1; |
| } |
| |
| @Override |
| public void set(E o) { |
| checkState(last != -1); |
| |
| AbstractList.this.set(last, o); |
| } |
| } |
| |
| private static class SubList<E> extends AbstractList<E> { |
| private final List<E> wrapped; |
| private final int fromIndex; |
| private int size; |
| |
| public SubList(List<E> wrapped, int fromIndex, int toIndex) { |
| checkCriticalPositionIndexes(fromIndex, toIndex, wrapped.size()); |
| |
| this.wrapped = wrapped; |
| this.fromIndex = fromIndex; |
| this.size = toIndex - fromIndex; |
| } |
| |
| @Override |
| public void add(int index, E element) { |
| checkPositionIndex(index, size); |
| |
| wrapped.add(fromIndex + index, element); |
| size++; |
| } |
| |
| @Override |
| public E get(int index) { |
| checkElementIndex(index, size); |
| |
| return wrapped.get(fromIndex + index); |
| } |
| |
| @Override |
| public E remove(int index) { |
| checkElementIndex(index, size); |
| |
| E result = wrapped.remove(fromIndex + index); |
| size--; |
| return result; |
| } |
| |
| @Override |
| public E set(int index, E element) { |
| checkElementIndex(index, size); |
| |
| return wrapped.set(fromIndex + index, element); |
| } |
| |
| @Override |
| public int size() { |
| return size; |
| } |
| } |
| |
| protected transient int modCount; |
| |
| protected AbstractList() { |
| } |
| |
| @Override |
| public boolean add(E obj) { |
| add(size(), obj); |
| return true; |
| } |
| |
| @Override |
| public void add(int index, E element) { |
| throw new UnsupportedOperationException("Add not supported on this list"); |
| } |
| |
| @Override |
| public boolean addAll(int index, Collection<? extends E> c) { |
| checkNotNull(c); |
| |
| boolean changed = false; |
| for (E e : c) { |
| add(index++, e); |
| changed = true; |
| } |
| return changed; |
| } |
| |
| @Override |
| public void clear() { |
| removeRange(0, size()); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o == this) { |
| return true; |
| } |
| |
| if (!(o instanceof List)) { |
| return false; |
| } |
| |
| List<?> other = (List<?>) o; |
| if (size() != other.size()) { |
| return false; |
| } |
| |
| Iterator<?> iterOther = other.iterator(); |
| for (E elem : this) { |
| Object elemOther = iterOther.next(); |
| if (!Objects.equals(elem, elemOther)) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Collections.hashCode(this); |
| } |
| |
| @Override |
| public int indexOf(Object toFind) { |
| for (int i = 0, n = size(); i < n; ++i) { |
| if (Objects.equals(toFind, get(i))) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| @Override |
| public Iterator<E> iterator() { |
| return new IteratorImpl(); |
| } |
| |
| @Override |
| public int lastIndexOf(Object toFind) { |
| for (int i = size() - 1; i > -1; --i) { |
| if (Objects.equals(toFind, get(i))) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| @Override |
| public ListIterator<E> listIterator() { |
| return listIterator(0); |
| } |
| |
| @Override |
| public ListIterator<E> listIterator(int from) { |
| return new ListIteratorImpl(from); |
| } |
| |
| @Override |
| public E remove(int index) { |
| throw new UnsupportedOperationException("Remove not supported on this list"); |
| } |
| |
| @Override |
| public E set(int index, E o) { |
| throw new UnsupportedOperationException("Set not supported on this list"); |
| } |
| |
| @Override |
| @JsNonNull |
| public List<E> subList(int fromIndex, int toIndex) { |
| return new SubList<E>(this, fromIndex, toIndex); |
| } |
| |
| protected void removeRange(int fromIndex, int endIndex) { |
| ListIterator<E> iter = listIterator(fromIndex); |
| for (int i = fromIndex; i < endIndex; ++i) { |
| iter.next(); |
| iter.remove(); |
| } |
| } |
| } |