KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > util > AutoPopulatingList


1 /*
2  * Copyright 2002-2006 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.util;
18
19 import java.lang.reflect.Modifier JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Collection JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.ListIterator JavaDoc;
25
26 /**
27  * Simple {@link List} wrapper class that allows for elements to be
28  * automatically populated as they are requested. This is particularly
29  * useful for data binding to {@link List Lists}, allowing for elements
30  * to be created and added to the {@link List} in a "just in time" fashion.
31  *
32  * <p>Note: This class is not thread-safe. To create a thread-safe version,
33  * use the {@link java.util.Collections#synchronizedList} utility methods.
34  *
35  * <p>Inspired by <code>LazyList</code> from Commons Collections.
36  *
37  * @author Rob Harrop
38  * @author Juergen Hoeller
39  * @since 2.0
40  */

41 public class AutoPopulatingList implements List JavaDoc {
42
43     /**
44      * The {@link List} that all operations are eventually delegated to.
45      */

46     private final List JavaDoc backingList;
47
48     /**
49      * The {@link ElementFactory} to use to create new {@link List} elements
50      * on demand.
51      */

52     private final ElementFactory elementFactory;
53
54
55     /**
56      * Creates a new <code>AutoPopulatingList</code> that is backed by a standard
57      * {@link ArrayList} and adds new instances of the supplied {@link Class element Class}
58      * to the backing {@link List} on demand.
59      */

60     public AutoPopulatingList(Class JavaDoc elementClass) {
61         this(new ArrayList JavaDoc(), elementClass);
62     }
63
64     /**
65      * Creates a new <code>AutoPopulatingList</code> that is backed by the supplied {@link List}
66      * and adds new instances of the supplied {@link Class element Class} to the backing
67      * {@link List} on demand.
68      */

69     public AutoPopulatingList(List JavaDoc backingList, Class JavaDoc elementClass) {
70         this(backingList, new ReflectiveElementFactory(elementClass));
71     }
72
73     /**
74      * Creates a new <code>AutoPopulatingList</code> that is backed by a standard
75      * {@link ArrayList} and creates new elements on demand using the supplied {@link ElementFactory}.
76      */

77     public AutoPopulatingList(ElementFactory elementFactory) {
78         this(new ArrayList JavaDoc(), elementFactory);
79     }
80
81     /**
82      * Creates a new <code>AutoPopulatingList</code> that is backed by the supplied {@link List}
83      * and creates new elements on demand using the supplied {@link ElementFactory}.
84      */

85     public AutoPopulatingList(List JavaDoc backingList, ElementFactory elementFactory) {
86         Assert.notNull(backingList, "Backing List must not be null");
87         Assert.notNull(elementFactory, "Element factory must not be null");
88         this.backingList = backingList;
89         this.elementFactory = elementFactory;
90     }
91
92
93     public void add(int index, Object JavaDoc element) {
94         this.backingList.add(index, element);
95     }
96
97     public boolean add(Object JavaDoc o) {
98         return this.backingList.add(o);
99     }
100
101     public boolean addAll(Collection JavaDoc c) {
102         return this.backingList.addAll(c);
103     }
104
105     public boolean addAll(int index, Collection JavaDoc c) {
106         return this.backingList.addAll(index, c);
107     }
108
109     public void clear() {
110         this.backingList.clear();
111     }
112
113     public boolean contains(Object JavaDoc o) {
114         return this.backingList.contains(o);
115     }
116
117     public boolean containsAll(Collection JavaDoc c) {
118         return this.backingList.containsAll(c);
119     }
120
121     public boolean equals(Object JavaDoc o) {
122         return this.backingList.equals(o);
123     }
124
125     /**
126      * Get the element at the supplied index, creating it if there is
127      * no element at that index.
128      */

129     public Object JavaDoc get(int index) {
130         int backingListSize = this.backingList.size();
131
132         Object JavaDoc element = null;
133         if (index < backingListSize) {
134             element = this.backingList.get(index);
135             if (element == null) {
136                 element = this.elementFactory.createElement(index);
137                 this.backingList.set(index, element);
138             }
139         }
140         else {
141             for (int x = backingListSize; x < index; x++) {
142                 this.backingList.add(null);
143             }
144             element = this.elementFactory.createElement(index);
145             this.backingList.add(element);
146         }
147         return element;
148     }
149
150     public int hashCode() {
151         return this.backingList.hashCode();
152     }
153
154     public int indexOf(Object JavaDoc o) {
155         return this.backingList.indexOf(o);
156     }
157
158     public boolean isEmpty() {
159         return this.backingList.isEmpty();
160     }
161
162     public Iterator JavaDoc iterator() {
163         return this.backingList.iterator();
164     }
165
166     public int lastIndexOf(Object JavaDoc o) {
167         return this.backingList.lastIndexOf(o);
168     }
169
170     public ListIterator JavaDoc listIterator() {
171         return this.backingList.listIterator();
172     }
173
174     public ListIterator JavaDoc listIterator(int index) {
175         return this.backingList.listIterator(index);
176     }
177
178     public Object JavaDoc remove(int index) {
179         return this.backingList.remove(index);
180     }
181
182     public boolean remove(Object JavaDoc o) {
183         return this.backingList.remove(o);
184     }
185
186     public boolean removeAll(Collection JavaDoc c) {
187         return this.backingList.removeAll(c);
188     }
189
190     public boolean retainAll(Collection JavaDoc c) {
191         return this.backingList.retainAll(c);
192     }
193
194     public Object JavaDoc set(int index, Object JavaDoc element) {
195         return this.backingList.set(index, element);
196     }
197
198     public int size() {
199         return this.backingList.size();
200     }
201
202     public List JavaDoc subList(int fromIndex, int toIndex) {
203         return this.backingList.subList(fromIndex, toIndex);
204     }
205
206     public Object JavaDoc[] toArray() {
207         return this.backingList.toArray();
208     }
209
210     public Object JavaDoc[] toArray(Object JavaDoc[] a) {
211         return this.backingList.toArray(a);
212     }
213
214
215     /**
216      * Factory interface for creating elements for an index-based access
217      * data structure such as a {@link java.util.List}.
218      */

219     public interface ElementFactory {
220
221         /**
222          * Create the element for the supplied index.
223          * @return the element object
224          * @throws ElementInstantiationException if the instantiation process failed
225          * (any exception thrown by a target constructor should be propagated as-is)
226          */

227         Object JavaDoc createElement(int index) throws ElementInstantiationException;
228     }
229
230
231     /**
232      * Exception to be thrown from ElementFactory.
233      */

234     public static class ElementInstantiationException extends RuntimeException JavaDoc {
235
236         public ElementInstantiationException(String JavaDoc msg) {
237             super(msg);
238         }
239     }
240
241
242     /**
243      * Reflective implementation of the ElementFactory interface,
244      * using <code>Class.newInstance()</code> on a given element class.
245      * @see java.lang.Class#newInstance()
246      */

247     private static class ReflectiveElementFactory implements ElementFactory {
248
249         private final Class JavaDoc elementClass;
250
251         public ReflectiveElementFactory(Class JavaDoc elementClass) {
252             Assert.notNull(elementClass, "Element clas must not be null");
253             Assert.isTrue(!elementClass.isInterface(), "Element class must not be an interface type");
254             Assert.isTrue(!Modifier.isAbstract(elementClass.getModifiers()), "Element class cannot be an abstract class");
255             this.elementClass = elementClass;
256         }
257
258         public Object JavaDoc createElement(int index) {
259             try {
260                 return this.elementClass.newInstance();
261             }
262             catch (InstantiationException JavaDoc ex) {
263                 throw new ElementInstantiationException("Unable to instantiate element class [" +
264                         this.elementClass.getName() + "]. Root cause is " + ex);
265             }
266             catch (IllegalAccessException JavaDoc ex) {
267                 throw new ElementInstantiationException("Cannot access element class [" +
268                         this.elementClass.getName() + "]. Root cause is " + ex);
269             }
270         }
271     }
272
273 }
274
Popular Tags