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.collections.list;
18
19 import java.util.Collection;
20 import java.util.List;
21 import java.util.ListIterator;
22
23 import org.apache.commons.collections.Transformer;
24 import org.apache.commons.collections.collection.TransformedCollection;
25 import org.apache.commons.collections.iterators.AbstractListIteratorDecorator;
26
27 /**
28 * Decorates another <code>List</code> to transform objects that are added.
29 * <p>
30 * The add and set methods are affected by this class.
31 * Thus objects must be removed or searched for using their transformed form.
32 * For example, if the transformation converts Strings to Integers, you must
33 * use the Integer form to remove objects.
34 * <p>
35 * This class is Serializable from Commons Collections 3.1.
36 *
37 * @since 3.0
38 * @version $Id: TransformedList.java 1451177 2013-02-28 11:42:31Z tn $
39 */
40 public class TransformedList<E> extends TransformedCollection<E> implements List<E> {
41
42 /** Serialization version */
43 private static final long serialVersionUID = 1077193035000013141L;
44
45 /**
46 * Factory method to create a transforming list.
47 * <p>
48 * If there are any elements already in the list being decorated, they
49 * are NOT transformed.
50 * Contrast this with {@link #transformedList(List, Transformer)}.
51 *
52 * @param <E> the type of the elements in the list
53 * @param list the list to decorate, must not be null
54 * @param transformer the transformer to use for conversion, must not be null
55 * @return a new transformed list
56 * @throws IllegalArgumentException if list or transformer is null
57 */
58 public static <E> TransformedList<E> transformingList(final List<E> list,
59 final Transformer<? super E, ? extends E> transformer) {
60 return new TransformedList<E>(list, transformer);
61 }
62
63 /**
64 * Factory method to create a transforming list that will transform
65 * existing contents of the specified list.
66 * <p>
67 * If there are any elements already in the list being decorated, they
68 * will be transformed by this method.
69 * Contrast this with {@link #transformingList(List, Transformer)}.
70 *
71 * @param <E> the type of the elements in the list
72 * @param list the list to decorate, must not be null
73 * @param transformer the transformer to use for conversion, must not be null
74 * @return a new transformed List
75 * @throws IllegalArgumentException if list or transformer is null
76 * @since 4.0
77 */
78 public static <E> TransformedList<E> transformedList(final List<E> list,
79 final Transformer<? super E, ? extends E> transformer) {
80 final TransformedList<E> decorated = new TransformedList<E>(list, transformer);
81 if (transformer != null && list != null && list.size() > 0) {
82 @SuppressWarnings("unchecked") // list is of type E
83 final E[] values = (E[]) list.toArray();
84 list.clear();
85 for (final E value : values) {
86 decorated.decorated().add(transformer.transform(value));
87 }
88 }
89 return decorated;
90 }
91
92 //-----------------------------------------------------------------------
93 /**
94 * Constructor that wraps (not copies).
95 * <p>
96 * If there are any elements already in the list being decorated, they
97 * are NOT transformed.
98 *
99 * @param list the list to decorate, must not be null
100 * @param transformer the transformer to use for conversion, must not be null
101 * @throws IllegalArgumentException if list or transformer is null
102 */
103 protected TransformedList(final List<E> list, final Transformer<? super E, ? extends E> transformer) {
104 super(list, transformer);
105 }
106
107 /**
108 * Gets the decorated list.
109 *
110 * @return the decorated list
111 */
112 protected List<E> getList() {
113 return (List<E>) collection;
114 }
115
116 //-----------------------------------------------------------------------
117
118 public E get(final int index) {
119 return getList().get(index);
120 }
121
122 public int indexOf(final Object object) {
123 return getList().indexOf(object);
124 }
125
126 public int lastIndexOf(final Object object) {
127 return getList().lastIndexOf(object);
128 }
129
130 public E remove(final int index) {
131 return getList().remove(index);
132 }
133
134 //-----------------------------------------------------------------------
135
136 public void add(final int index, E object) {
137 object = transform(object);
138 getList().add(index, object);
139 }
140
141 public boolean addAll(final int index, Collection<? extends E> coll) {
142 coll = transform(coll);
143 return getList().addAll(index, coll);
144 }
145
146 public ListIterator<E> listIterator() {
147 return listIterator(0);
148 }
149
150 public ListIterator<E> listIterator(final int i) {
151 return new TransformedListIterator(getList().listIterator(i));
152 }
153
154 public E set(final int index, E object) {
155 object = transform(object);
156 return getList().set(index, object);
157 }
158
159 public List<E> subList(final int fromIndex, final int toIndex) {
160 final List<E> sub = getList().subList(fromIndex, toIndex);
161 return new TransformedList<E>(sub, transformer);
162 }
163
164 /**
165 * Inner class Iterator for the TransformedList
166 */
167 protected class TransformedListIterator extends AbstractListIteratorDecorator<E> {
168
169 /**
170 * Create a new transformed list iterator.
171 *
172 * @param iterator the list iterator to decorate
173 */
174 protected TransformedListIterator(final ListIterator<E> iterator) {
175 super(iterator);
176 }
177
178 @Override
179 public void add(E object) {
180 object = transform(object);
181 iterator.add(object);
182 }
183
184 @Override
185 public void set(E object) {
186 object = transform(object);
187 iterator.set(object);
188 }
189 }
190
191 }