1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.collections4.list;
18
19 import java.util.Collection;
20 import java.util.List;
21 import java.util.ListIterator;
22
23 import org.apache.commons.collections4.Predicate;
24 import org.apache.commons.collections4.collection.PredicatedCollection;
25 import org.apache.commons.collections4.iterators.AbstractListIteratorDecorator;
26
27 /**
28 * Decorates another {@code List} to validate that all additions
29 * match a specified predicate.
30 * <p>
31 * This list exists to provide validation for the decorated list.
32 * It is normally created to decorate an empty list.
33 * If an object cannot be added to the list, an IllegalArgumentException is thrown.
34 * </p>
35 * <p>
36 * One usage would be to ensure that no null entries are added to the list.
37 * </p>
38 * <pre>
39 * {@code
40 * List<String> list =
41 * PredicatedList.predicatedList(new ArrayList<String>(), PredicateUtils.notNullPredicate());
42 * }
43 * </pre>
44 * <p>
45 * This class is Serializable from Commons Collections 3.1.
46 * </p>
47 *
48 * @param <E> the type of the elements in the list.
49 * @since 3.0
50 */
51 public class PredicatedList<E> extends PredicatedCollection<E> implements List<E> {
52
53 /**
54 * Inner class Iterator for the PredicatedList
55 */
56 protected class PredicatedListIterator extends AbstractListIteratorDecorator<E> {
57
58 /**
59 * Create a new predicated list iterator.
60 *
61 * @param iterator the list iterator to decorate
62 */
63 protected PredicatedListIterator(final ListIterator<E> iterator) {
64 super(iterator);
65 }
66
67 @Override
68 public void add(final E object) {
69 validate(object);
70 getListIterator().add(object);
71 }
72
73 @Override
74 public void set(final E object) {
75 validate(object);
76 getListIterator().set(object);
77 }
78 }
79
80 /** Serialization version */
81 private static final long serialVersionUID = -5722039223898659102L;
82
83 /**
84 * Factory method to create a predicated (validating) list.
85 * <p>
86 * If there are any elements already in the list being decorated, they
87 * are validated.
88 *
89 * @param <T> the type of the elements in the list
90 * @param list the list to decorate, must not be null
91 * @param predicate the predicate to use for validation, must not be null
92 * @return a new predicated list
93 * @throws NullPointerException if list or predicate is null
94 * @throws IllegalArgumentException if the list contains invalid elements
95 * @since 4.0
96 */
97 public static <T> PredicatedList<T> predicatedList(final List<T> list, final Predicate<? super T> predicate) {
98 return new PredicatedList<>(list, predicate);
99 }
100
101 /**
102 * Constructor that wraps (not copies).
103 * <p>
104 * If there are any elements already in the list being decorated, they
105 * are validated.
106 *
107 * @param list the list to decorate, must not be null
108 * @param predicate the predicate to use for validation, must not be null
109 * @throws NullPointerException if list or predicate is null
110 * @throws IllegalArgumentException if the list contains invalid elements
111 */
112 protected PredicatedList(final List<E> list, final Predicate<? super E> predicate) {
113 super(list, predicate);
114 }
115
116 @Override
117 public void add(final int index, final E object) {
118 validate(object);
119 decorated().add(index, object);
120 }
121
122 @Override
123 public boolean addAll(final int index, final Collection<? extends E> coll) {
124 for (final E aColl : coll) {
125 validate(aColl);
126 }
127 return decorated().addAll(index, coll);
128 }
129
130 /**
131 * Gets the list being decorated.
132 *
133 * @return the decorated list
134 */
135 @Override
136 protected List<E> decorated() {
137 return (List<E>) super.decorated();
138 }
139
140 @Override
141 public boolean equals(final Object object) {
142 return object == this || decorated().equals(object);
143 }
144
145 @Override
146 public E get(final int index) {
147 return decorated().get(index);
148 }
149
150 @Override
151 public int hashCode() {
152 return decorated().hashCode();
153 }
154
155 @Override
156 public int indexOf(final Object object) {
157 return decorated().indexOf(object);
158 }
159
160 @Override
161 public int lastIndexOf(final Object object) {
162 return decorated().lastIndexOf(object);
163 }
164
165 @Override
166 public ListIterator<E> listIterator() {
167 return listIterator(0);
168 }
169
170 @Override
171 public ListIterator<E> listIterator(final int i) {
172 return new PredicatedListIterator(decorated().listIterator(i));
173 }
174
175 @Override
176 public E remove(final int index) {
177 return decorated().remove(index);
178 }
179
180 @Override
181 public E set(final int index, final E object) {
182 validate(object);
183 return decorated().set(index, object);
184 }
185
186 @Override
187 public List<E> subList(final int fromIndex, final int toIndex) {
188 final List<E> sub = decorated().subList(fromIndex, toIndex);
189 return new PredicatedList<>(sub, predicate);
190 }
191
192 }