    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.List;
    021import java.util.ListIterator;
    022
    023import org.apache.commons.collections4.Predicate;
    024import org.apache.commons.collections4.collection.PredicatedCollection;
    025import org.apache.commons.collections4.iterators.AbstractListIteratorDecorator;
    026
    027/**
    028 * Decorates another <code>List</code> to validate that all additions
    029 * match a specified predicate.
    030 * <p>
    031 * This list exists to provide validation for the decorated list.
    032 * It is normally created to decorate an empty list.
    033 * If an object cannot be added to the list, an IllegalArgumentException is thrown.
    034 * <p>
    035 * One usage would be to ensure that no null entries are added to the list.
    036 * <pre>
    037 * {@code
    038 * List<String> list =
    039 *   PredicatedList.predicatedList(new ArrayList<String>(), PredicateUtils.notNullPredicate());
    040 * }
    041 * </pre>
    042 * <p>
    043 * This class is Serializable from Commons Collections 3.1.
    044 *
    045 * @since 3.0
    046 */
    047public class PredicatedList<E> extends PredicatedCollection<E> implements List<E> {
    048
    049    /** Serialization version */
    050    private static final long serialVersionUID = -5722039223898659102L;
    051
    052    /**
    053     * Factory method to create a predicated (validating) list.
    054     * <p>
    055     * If there are any elements already in the list being decorated, they
    056     * are validated.
    057     *
    058     * @param <T> the type of the elements in the list
    059     * @param list  the list to decorate, must not be null
    060     * @param predicate  the predicate to use for validation, must not be null
    061     * @return a new predicated list
    062     * @throws NullPointerException if list or predicate is null
    063     * @throws IllegalArgumentException if the list contains invalid elements
    064     * @since 4.0
    065     */
    066    public static <T> PredicatedList<T> predicatedList(final List<T> list, final Predicate<? super T> predicate) {
    067        return new PredicatedList<>(list, predicate);
    068    }
    069
    070    //-----------------------------------------------------------------------
    071    /**
    072     * Constructor that wraps (not copies).
    073     * <p>
    074     * If there are any elements already in the list being decorated, they
    075     * are validated.
    076     *
    077     * @param list  the list to decorate, must not be null
    078     * @param predicate  the predicate to use for validation, must not be null
    079     * @throws NullPointerException if list or predicate is null
    080     * @throws IllegalArgumentException if the list contains invalid elements
    081     */
    082    protected PredicatedList(final List<E> list, final Predicate<? super E> predicate) {
    083        super(list, predicate);
    084    }
    085
    086    /**
    087     * Gets the list being decorated.
    088     *
    089     * @return the decorated list
    090     */
    091    @Override
    092    protected List<E> decorated() {
    093        return (List<E>) super.decorated();
    094    }
    095
    096    @Override
    097    public boolean equals(final Object object) {
    098        return object == this || decorated().equals(object);
    099    }
    100
    101    @Override
    102    public int hashCode() {
    103        return decorated().hashCode();
    104    }
    105
    106    //-----------------------------------------------------------------------
    107
    108    @Override
    109    public E get(final int index) {
    110        return decorated().get(index);
    111    }
    112
    113    @Override
    114    public int indexOf(final Object object) {
    115        return decorated().indexOf(object);
    116    }
    117
    118    @Override
    119    public int lastIndexOf(final Object object) {
    120        return decorated().lastIndexOf(object);
    121    }
    122
    123    @Override
    124    public E remove(final int index) {
    125        return decorated().remove(index);
    126    }
    127
    128    //-----------------------------------------------------------------------
    129
    130    @Override
    131    public void add(final int index, final E object) {
    132        validate(object);
    133        decorated().add(index, object);
    134    }
    135
    136    @Override
    137    public boolean addAll(final int index, final Collection<? extends E> coll) {
    138        for (final E aColl : coll) {
    139            validate(aColl);
    140        }
    141        return decorated().addAll(index, coll);
    142    }
    143
    144    @Override
    145    public ListIterator<E> listIterator() {
    146        return listIterator(0);
    147    }
    148
    149    @Override
    150    public ListIterator<E> listIterator(final int i) {
    151        return new PredicatedListIterator(decorated().listIterator(i));
    152    }
    153
    154    @Override
    155    public E set(final int index, final E object) {
    156        validate(object);
    157        return decorated().set(index, object);
    158    }
    159
    160    @Override
    161    public List<E> subList(final int fromIndex, final int toIndex) {
    162        final List<E> sub = decorated().subList(fromIndex, toIndex);
    163        return new PredicatedList<>(sub, predicate);
    164    }
    165
    166    /**
    167     * Inner class Iterator for the PredicatedList
    168     */
    169    protected class PredicatedListIterator extends AbstractListIteratorDecorator<E> {
    170
    171        /**
    172         * Create a new predicated list iterator.
    173         *
    174         * @param iterator  the list iterator to decorate
    175         */
    176        protected PredicatedListIterator(final ListIterator<E> iterator) {
    177            super(iterator);
    178        }
    179
    180        @Override
    181        public void add(final E object) {
    182            validate(object);
    183            getListIterator().add(object);
    184        }
    185
    186        @Override
    187        public void set(final E object) {
    188            validate(object);
    189            getListIterator().set(object);
    190        }
    191    }
    192
    193}