001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.collections4.list;
018
019import java.util.Collection;
020import java.util.Iterator;
021import java.util.List;
022import java.util.ListIterator;
023import java.util.function.Predicate;
024
025import org.apache.commons.collections4.BoundedCollection;
026import org.apache.commons.collections4.iterators.AbstractListIteratorDecorator;
027import org.apache.commons.collections4.iterators.UnmodifiableIterator;
028
029/**
030 * Decorates another {@code List} to fix the size preventing add/remove.
031 * <p>
032 * The add, remove, clear and retain operations are unsupported.
033 * The set method is allowed (as it doesn't change the list size).
034 * </p>
035 * <p>
036 * NOTE:
037 * Modifying the decorated list directly would results in influencing the outcome
038 * of method calls on this object. For example, the bounds of this list would reflect
039 * a newly added object to the underlying list.
040 * </p>
041 * <p>
042 * This class is Serializable from Commons Collections 3.1.
043 * </p>
044 *
045 * @param <E> the type of elements in this collection
046 * @since 3.0
047 */
048public class FixedSizeList<E>
049        extends AbstractSerializableListDecorator<E>
050        implements BoundedCollection<E> {
051
052    /**
053     * List iterator that only permits changes via set()
054     */
055    private final class FixedSizeListIterator extends AbstractListIteratorDecorator<E> {
056        protected FixedSizeListIterator(final ListIterator<E> iterator) {
057            super(iterator);
058        }
059        @Override
060        public void add(final Object object) {
061            throw unsupportedOperationException();
062        }
063        @Override
064        public void remove() {
065            throw unsupportedOperationException();
066        }
067    }
068
069    /** Serialization version */
070    private static final long serialVersionUID = -2218010673611160319L;
071
072    /**
073     * Factory method to create a fixed size list.
074     *
075     * @param <E> the type of the elements in the list
076     * @param list  the list to decorate, must not be null
077     * @return a new fixed size list
078     * @throws NullPointerException if list is null
079     * @since 4.0
080     */
081    public static <E> FixedSizeList<E> fixedSizeList(final List<E> list) {
082        return new FixedSizeList<>(list);
083    }
084
085    private static UnsupportedOperationException unsupportedOperationException() {
086        return new UnsupportedOperationException("List is fixed size");
087    }
088
089    /**
090     * Constructor that wraps (not copies).
091     *
092     * @param list  the list to decorate, must not be null
093     * @throws NullPointerException if list is null
094     */
095    protected FixedSizeList(final List<E> list) {
096        super(list);
097    }
098
099    @Override
100    public boolean add(final E object) {
101        throw unsupportedOperationException();
102    }
103
104    @Override
105    public void add(final int index, final E object) {
106        throw unsupportedOperationException();
107    }
108
109    @Override
110    public boolean addAll(final Collection<? extends E> coll) {
111        throw unsupportedOperationException();
112    }
113
114    @Override
115    public boolean addAll(final int index, final Collection<? extends E> coll) {
116        throw unsupportedOperationException();
117    }
118
119    @Override
120    public void clear() {
121        throw unsupportedOperationException();
122    }
123
124    @Override
125    public E get(final int index) {
126        return decorated().get(index);
127    }
128
129    @Override
130    public int indexOf(final Object object) {
131        return decorated().indexOf(object);
132    }
133
134    @Override
135    public boolean isFull() {
136        return true;
137    }
138
139    @Override
140    public Iterator<E> iterator() {
141        return UnmodifiableIterator.unmodifiableIterator(decorated().iterator());
142    }
143
144    @Override
145    public int lastIndexOf(final Object object) {
146        return decorated().lastIndexOf(object);
147    }
148
149    @Override
150    public ListIterator<E> listIterator() {
151        return new FixedSizeListIterator(decorated().listIterator(0));
152    }
153
154    @Override
155    public ListIterator<E> listIterator(final int index) {
156        return new FixedSizeListIterator(decorated().listIterator(index));
157    }
158
159    @Override
160    public int maxSize() {
161        return size();
162    }
163
164    @Override
165    public E remove(final int index) {
166        throw unsupportedOperationException();
167    }
168
169    @Override
170    public boolean remove(final Object object) {
171        throw unsupportedOperationException();
172    }
173
174    @Override
175    public boolean removeAll(final Collection<?> coll) {
176        throw unsupportedOperationException();
177    }
178
179    /**
180     * @since 4.4
181     */
182    @Override
183    public boolean removeIf(final Predicate<? super E> filter) {
184        throw unsupportedOperationException();
185    }
186
187    @Override
188    public boolean retainAll(final Collection<?> coll) {
189        throw unsupportedOperationException();
190    }
191
192    @Override
193    public E set(final int index, final E object) {
194        return decorated().set(index, object);
195    }
196
197    @Override
198    public List<E> subList(final int fromIndex, final int toIndex) {
199        final List<E> sub = decorated().subList(fromIndex, toIndex);
200        return new FixedSizeList<>(sub);
201    }
202
203}