class PotentiallyUnmodifiableList<T> extends ArrayList<T> {
    /** serialVersionUID. */
    static final long serialVersionUID = 1L;

    /** Whether or not the list is modifiable. */
    boolean modifiable = true;

    /**
     * Constructor.
     */
    PotentiallyUnmodifiableList() {
        super();
    }

    /**
     * Constructor.
     *
     * @param sizeHint
     *            the size hint
     */
    PotentiallyUnmodifiableList(final int sizeHint) {
        super(sizeHint);
    }

    /**
     * Constructor.
     *
     * @param collection
     *            the initial elements.
     */
    PotentiallyUnmodifiableList(final Collection<T> collection) {
        super(collection);
    }

    // Keep Scrutinizer happy
    @Override
    public boolean equals(final Object o) {
        return super.equals(o);
    }

    // Keep Scrutinizer happy
    @Override
    public int hashCode() {
        return super.hashCode();
    }

    /** Make this list unmodifiable. */
    void makeUnmodifiable() {
        modifiable = false;
    }

    @Override
    public boolean add(final T element) {
        if (!modifiable) {
            throw new IllegalArgumentException("List is immutable");
        } else {
            return super.add(element);
        }
    }

    @Override
    public void add(final int index, final T element) {
        if (!modifiable) {
            throw new IllegalArgumentException("List is immutable");
        } else {
            super.add(index, element);
        }
    }

    @Override
    public boolean remove(final Object o) {
        if (!modifiable) {
            throw new IllegalArgumentException("List is immutable");
        } else {
            return super.remove(o);
        }
    }

    @Override
    public T remove(final int index) {
        if (!modifiable) {
            throw new IllegalArgumentException("List is immutable");
        } else {
            return super.remove(index);
        }
    }

    @Override
    public boolean addAll(final Collection<? extends T> c) {
        if (!modifiable && !c.isEmpty()) {
            throw new IllegalArgumentException("List is immutable");
        } else {
            return super.addAll(c);
        }
    }

    @Override
    public boolean addAll(final int index, final Collection<? extends T> c) {
        if (!modifiable && !c.isEmpty()) {
            throw new IllegalArgumentException("List is immutable");
        } else {
            return super.addAll(index, c);
        }
    }

    @Override
    public boolean removeAll(final Collection<?> c) {
        if (!modifiable && !c.isEmpty()) {
            throw new IllegalArgumentException("List is immutable");
        } else {
            return super.removeAll(c);
        }
    }

    @Override
    public boolean retainAll(final Collection<?> c) {
        if (!modifiable && !isEmpty()) {
            throw new IllegalArgumentException("List is immutable");
        } else {
            return super.retainAll(c);
        }
    }

    @Override
    public void clear() {
        if (!modifiable && !isEmpty()) {
            throw new IllegalArgumentException("List is immutable");
        } else {
            super.clear();
        }
    }

    @Override
    public T set(final int index, final T element) {
        if (!modifiable) {
            throw new IllegalArgumentException("List is immutable");
        } else {
            return super.set(index, element);
        }
    }

    // Provide replacement iterators so that there is no chance of a thread that
    // is trying to sort the empty list causing a ConcurrentModificationException
    // in another thread that is iterating over the empty list (#334)

    @Override
    public Iterator<T> iterator() {
        final Iterator<T> iterator = super.iterator();
        return new Iterator<T>() {
            @Override
            public boolean hasNext() {
                if (isEmpty()) {
                    return false;
                } else {
                    return iterator.hasNext();
                }
            }

            @Override
            public T next() {
                return iterator.next();
            }

            @Override
            public void remove() {
                if (!modifiable) {
                    throw new IllegalArgumentException("List is immutable");
                } else {
                    iterator.remove();
                }
            }
        };
    }

    @Override
    public ListIterator<T> listIterator() {
        final ListIterator<T> iterator = super.listIterator();
        return new ListIterator<T>() {
            @Override
            public boolean hasNext() {
                if (isEmpty()) {
                    return false;
                } else {
                    return iterator.hasNext();
                }
            }

            @Override
            public T next() {
                return iterator.next();
            }

            @Override
            public boolean hasPrevious() {<FILL_FUNCTION_BODY>}

            @Override
            public T previous() {
                return iterator.previous();
            }

            @Override
            public int nextIndex() {
                if (isEmpty()) {
                    return 0;
                } else {
                    return iterator.nextIndex();
                }
            }

            @Override
            public int previousIndex() {
                if (isEmpty()) {
                    return -1;
                } else {
                    return iterator.previousIndex();
                }
            }

            @Override
            public void remove() {
                if (!modifiable) {
                    throw new IllegalArgumentException("List is immutable");
                } else {
                    iterator.remove();
                }
            }

            @Override
            public void set(final T e) {
                if (!modifiable) {
                    throw new IllegalArgumentException("List is immutable");
                } else {
                    iterator.set(e);
                }
            }

            @Override
            public void add(final T e) {
                if (!modifiable) {
                    throw new IllegalArgumentException("List is immutable");
                } else {
                    iterator.add(e);
                }
            }
        };
    }
}

                if (isEmpty()) {
                    return false;
                } else {
                    return iterator.hasPrevious();
                }
            
<methods>public void <init>() ,public void <init>(int) ,public void <init>(Collection<? extends T>) ,public boolean add(T) ,public void add(int, T) ,public boolean addAll(Collection<? extends T>) ,public boolean addAll(int, Collection<? extends T>) ,public void clear() ,public java.lang.Object clone() ,public boolean contains(java.lang.Object) ,public void ensureCapacity(int) ,public boolean equals(java.lang.Object) ,public void forEach(Consumer<? super T>) ,public T get(int) ,public int hashCode() ,public int indexOf(java.lang.Object) ,public boolean isEmpty() ,public Iterator<T> iterator() ,public int lastIndexOf(java.lang.Object) ,public ListIterator<T> listIterator() ,public ListIterator<T> listIterator(int) ,public T remove(int) ,public boolean remove(java.lang.Object) ,public boolean removeAll(Collection<?>) ,public boolean removeIf(Predicate<? super T>) ,public void replaceAll(UnaryOperator<T>) ,public boolean retainAll(Collection<?>) ,public T set(int, T) ,public int size() ,public void sort(Comparator<? super T>) ,public Spliterator<T> spliterator() ,public List<T> subList(int, int) ,public java.lang.Object[] toArray() ,public T[] toArray(T[]) ,public void trimToSize() <variables>private static final java.lang.Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA,private static final int DEFAULT_CAPACITY,private static final java.lang.Object[] EMPTY_ELEMENTDATA,transient java.lang.Object[] elementData,private static final long serialVersionUID,private int size