View Javadoc

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 }